Search code examples
oauth-2.0jwtkeycloak

Passing parameters that end up in the JWT when requesting a service account token with Keycloak?


I would like to have a service account client in Keycloak where I can pass an arbitrary key/value when requesting an access token. This key/value pair should then end up as claim.

So when requesting a service account token with e.g.:

$ http --form --auth myclient:mysecret POST http://localhost:7070/realms/test/protocol/openid-connect/token \
  grant_type=client_credentials 
  foo=bar

I would like to see the extra parameter "foo=bar" as claim in the JWT:

{
  "iss": "http://localhost:7070/auth/realms/test",
  ...
  "clientId": "myclient",
  "foo": "bar"
}

Problems I encountered so far:

  • Custom request form parameters are ignored.
  • Custom scopes are always responed to with "Invalid scope".
  • I couldn't get Dynamic Scopes, an experimental extension, to work although it's shown as enabled and I added a client scope "foo:*"
  • URL Query Parameters or the raw form is not available in the AbstractOIDCProtocolMapper class so I can't get them from there in an Java extension

I'm currently using Keycloak 16 but also tried with the latest 20.

It does work with the urn:ietf:params:oauth:grant-type:token-exchange as Keycloak does not check the client scopes in that flow but the flow does not fit for my current case.

Any ideas what else I could do?


Solution

  • You try to build your own custom claim mapper as presented in here, which would read the custom claims from the application and add them to the token.

    Alternatively, you can also use script mappers to read the claims from the query parameters and add them to the token. Finally, you can also have a look at UMA flow and use the feature of pushing claims. The request could look like the following:

    curl -X POST -d "client_id=myclient" \
                 -d "client_secret=mysecret" \
                 -d "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
                 -d "claim_token_format=urn:ietf:params:oauth:token-type:jwt" \
                 -d "claim_token=ewogICAgImZvbyIgOiBbImJhciJdCn0="  \
                 -d "audience= myclient" \
                 "http://localhost:7070/realms/test/protocol/openid-connect/token"
    

    In the token you would have the following claim:

      "authorization": {
        "permissions": [
          {
            "claims": {
              "foo": [
                "bar"
              ]
            },
            "rsid": "...",
            "rsname": "..."
          }