osbuild-mock-openid-provider: support client_credentials grant type

Extend the implementation of mock openid server to take the `grant_type`
into consideration for the `/token` endpoint.

In addition to the previously supported `refresh_topen`, the
implementation now supports also `client_credentials`.

This is necessary to make it possible to use the mock server in
the `koji-osbuild` CI, because the builder plugin uses
`client_credentials` to get access token.

The implementation behaves in the following way:
 - For `refresh_token` grant type, it takes the `refresh_token` value
   from the request and adds it to the `rh-org-id` field in the custom
   claim, which is part of the returned token.
 - For `client_credentials` grant type, it takes the `client_secret`
   value from the request and adds it to the `rh-org-id` field in the
   custom claim, which is part of the returned token.

Requests without the supported `grant_type` set are rejected.

Modify affected test cases to specify `grant_type` when fetching a new
access token.
This commit is contained in:
Tomas Hozza 2022-08-04 12:36:57 +02:00 committed by Tomáš Hozza
parent 6ed9e48d87
commit 24c52c8d69
4 changed files with 29 additions and 8 deletions

View file

@ -90,13 +90,29 @@ func main() {
panic(err)
}
cc := customClaims{
Type: "Bearer",
ExpiresAt: 0,
IssuedAt: time.Now().Unix(),
// Use refresh_token as rh-org-id
RHOrgID: r.Form.Get("refresh_token"),
var cc customClaims
switch r.Form.Get("grant_type") {
case "refresh_token":
cc = customClaims{
Type: "Bearer",
ExpiresAt: 0,
IssuedAt: time.Now().Unix(),
// Use refresh_token as rh-org-id
RHOrgID: r.Form.Get("refresh_token"),
}
case "client_credentials":
cc = customClaims{
Type: "Bearer",
ExpiresAt: 0,
IssuedAt: time.Now().Unix(),
// Use client_secret as rh-org-id
RHOrgID: r.Form.Get("client_secret"),
}
default:
w.WriteHeader(http.StatusBadRequest)
return
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, cc)
token.Header["kid"] = "key-id"

View file

@ -528,11 +528,12 @@ KILL_PIDS+=("$!")
sudo systemctl restart osbuild-composer
until curl --output /dev/null --silent --fail localhost:8081/token; do
until curl --data "grant_type=refresh_token" --output /dev/null --silent --fail localhost:8081/token; do
sleep 0.5
done
TOKEN="$(curl --request POST \
--data "grant_type=refresh_token" \
--data "refresh_token=$REFRESH_TOKEN" \
--header "Content-Type: application/x-www-form-urlencoded" \
--silent \

View file

@ -60,6 +60,7 @@ function access_token {
function access_token_with_org_id {
local refresh_token="$1"
curl --request POST \
--data "grant_type=refresh_token" \
--data "refresh_token=$refresh_token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--silent \

View file

@ -127,7 +127,10 @@ class ComposerAPIClient:
self.auth_server = auth_server
def access_token(self):
resp = requests.post(self.auth_server + "/token", data={"refresh_token": self.refresh_token})
resp = requests.post(self.auth_server + "/token", data={
"grant_type": "refresh_token",
"refresh_token": self.refresh_token,
})
if resp.status_code != 200:
raise RuntimeError(f"failed to refresh token: {resp.text}")
return resp.json()["access_token"]