2

If I have a user that has authenticated with keycloak with public client C1 under realm R is there an endpoint I can hit in keycloak that will generate a new access token for a different public client C2 under the same realm R?

[Update #1] I tried using the refresh token to obtain a new access token for C2 client but I get the following error:

Invalid refresh token. Token client and authorized client don't match

[Update #2] So, the above gave me the idea of trying to use the exchange token grant type and I have it working now.

curl --request POST \
  'https://myhost.com.au/auth/realms/<my realm>/protocol/openid-connect/token' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
  --data-urlencode 'subject_token=<c1 access token>' \
  --data-urlencode 'subject_token_type=urn:ietf:params:oauth:token-type:access_token' \
  --data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:refresh_token' \
  --data-urlencode 'client_id=<c2 client id>'
Shane Rowatt
  • 1,951
  • 3
  • 27
  • 44
  • Why do you want to genrate new access token, if they are under same realm? – ravthiru Sep 18 '20 at 04:46
  • @ravthiru to get the scopes / claims of the new client into the access token. – Shane Rowatt Sep 18 '20 at 05:09
  • 1
    @ravthiru his questions totally makes sense: see https://www.keycloak.org/docs/latest/server_admin/#_role_scope_mappings realm roles aren't necessarilly exposed in an access token for all clients. – Olivier Tonglet Sep 18 '20 at 07:19

1 Answers1

1

Your question makes sense. Unfortunately the role scope mapping documentation is elusive about how to generate a new access token when switching to a different client.

There is an Oauth2 RFC about token exchange. As of Keycloak 11.0.2 token exchange is documented as a technology preview and has to be enabled with -Dkeycloak.profile.feature.token_exchange=enabled

You can exchange tokens this way (actually taken from the question):

Method: POST
URL: https://<keycloak.host>/auth/realms/myrealm/protocol/openid-connect/token
Body type: x-www-form-urlencoded
Form fields:    
. grant_type: urn:ietf:params:oauth:grant-type:token-exchange
. subject_token: <C1-access-token> 
. subject_token_type: urn:ietf:params:oauth:token-type:access_token
. requested_token_type=urn:ietf:params:oauth:token-type:refresh_token
. client_id: <C2-client-id>

Here is some context from the "role scope mapping" documentation intended for other readers.

When an OIDC access token or SAML assertion is created, all the user role mappings of the user are, by default, added as claims within the token or assertion. [...] access tokens are digitally signed and can actually be re-used by the application to invoke on other remotely secured REST services. This means that if an application gets compromised or there is a rogue client registered with the realm, attackers can get access tokens that have a broad range of permissions and your whole network is compromised. This is where role scope mappings becomes important.

Role Scope Mappings is a way to limit the roles that get declared inside an access token. When a client requests that a user be authenticated, the access token they receive back will only contain the role mappings you’ve explicitly specified for the client’s scope.

[...] To change this default behavior, you must explicitly turn off the Full Scope Allowed switch and declare the specific roles you want in each individual client. Alternatively, you can also use client scopes to define the same role scope mappings for a whole set of clients.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Olivier Tonglet
  • 3,312
  • 24
  • 40
  • @ShaneRowatt alright, thanks for letting me know. I updated my answer with your solution and extra references for future readers. – Olivier Tonglet Sep 22 '20 at 06:42