How to change the content of access tokens created through Keycloak token exchange

2.3k views Asked by At

My goal is it to get two resource server specific access tokens which contains only the data specific to the respective resource server.

I have the following setup: a public client is using 2 resource servers.

After configuring clients, users, realm roles, client scopes and by using the scope parameter, I am able to create 2 different, resource server specific access tokens:

{
  "exp": 1603234566,
  "iat": 1603216566,
  "jti": "13ae00ac-ce57-43ce-8b47-39ad6d5445cd",
  "iss": "http://localhost:8080/auth/realms/fitness-realm",
  "aud": "fitness-resource-server-1",
  "sub": "de1f0820-f4d9-49be-a6d1-c8faef083ffc",
  "typ": "Bearer",
  "azp": "fitness-client",
  "session_state": "47ea42f9-42ac-452e-9e54-be6d705e9a61",
  "acr": "1",
  "realm_access": {
    "roles": [
      "fitness_user"
    ]
  },
  "scope": "openid email profile client_scope_fitness_resource_server_1_roles",
  "email_verified": false,
  "preferred_username": "bill"
}

and

{
  "exp": 1603235280,
  "iat": 1603217280,
  "jti": "fb75a956-6ed4-4edd-8e20-2cd9678d4869",
  "iss": "http://localhost:8080/auth/realms/fitness-realm",
  "aud": "fitness-resource-server-2",
  "sub": "de1f0820-f4d9-49be-a6d1-c8faef083ffc",
  "typ": "Bearer",
  "azp": "fitness-client",
  "session_state": "966aa651-0534-43d4-9413-a8c141ee8549",
  "acr": "1",
  "realm_access": {
    "roles": [
      "fitness_user"
    ]
  },
  "scope": "openid email profile client_scope_fitness_resource_server_2_roles",
  "email_verified": false,
  "preferred_username": "bill"
}

During the login process I set the scope parameter to client_scope_fitness_resource_server_1_roles and get the first, resource server 1 specific access token. Since I get only one access token during the login process and my client is public, I want to use the resource server 1 to get the 2nd - resource server 2 specific - access token by using Keycloak’s internal token to internal token token exchange feature. I followed the instructions and I’am able to get the second token with this call:

curl -X POST http://localhost:8080/auth/realms/fitness-realm/protocol/openid-connect/token \
    -d "client_id=fitness-resource-server-1” \
    -d "client_secret=<my_secret>" \
    -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ 
    -d "subject_token=$FIRST_ACCESS_TOKEN" \
    -d "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \
    -d "audience=fitness-resource-server-2" |jq

But if I look inside of the second token it contains more informations I want:

{
  "exp": 1603234572,
  "iat": 1603216572,
  "jti": "4f4b0fb6-d759-4c6a-b35d-7e2a998b5a20",
  "iss": "http://localhost:8080/auth/realms/fitness-realm",
  "aud": [
    "other_resource_server",
    "fitness-client",
    "other_client",
    "account",
    "fitness-resource-server-2"
  ],
  "sub": "de1f0820-f4d9-49be-a6d1-c8faef083ffc",
  "typ": "Bearer",
  "azp": "fitness-resource-server-1",
  "session_state": "47ea42f9-42ac-452e-9e54-be6d705e9a61",
  "acr": "1",
  "realm_access": {
    "roles": [
      "fitness_user",
      "offline_access",
      "uma_authorization"
    ]
  },
  "scope": "email profile",
  "email_verified": false,
  "preferred_username": "bill"
}

My question is, how can I configure Keycloak that the second access token did not contain the roles "offline_access" and "uma_authorization" and the aud: "other_resource_server", "fitness-client", "other_client", "account”?

1

There are 1 answers

0
hb70muc On

I found the solution :-)

I have to change the resource server 2 settings - access type configuration from bearer only to confidential, disable all flows/grants, and with this change I am able to configure the Client Scope and Scope in the resource server 2 too.

It is not so nice that I have to change from bearer only to confidential even because I don't need confidential (flows/grants, credentials, etc.) but this makes it possible to change the access token output.