Our system uses a minimalistic token that does not include realm roles and client roles. Everything worked fine - after token validation we get all the information about user roles and groups from /userinfo. But recently we need to enable token-exchange functionality to use impersonation via Keycloak REST API and we have a problem - endpoint gives a 403 "Client not allowed to exchange" error until put the role information back into the token. Can you tell me if it's a bug or am I doing something wrong? I would like to continue to have a minimalistic token and use the token-exchange functionality.
For reproduce:
curl --location --request POST
'{{host}}/realms/{{realm}}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=our-public-client' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=moderator' \
--data-urlencode 'password=qwe123' \
curl --location --request POST '{{host}}/realms/{{realm}}/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=our-public-client' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange' \
--data-urlencode 'subject_token={{MODERATOR TOKEN HERE}}' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'requested_subject={{USERNAME OF REGULAR USER}}'
In this scenario I get an error:
{
"error": "access_denied",
"error_description": "The client is not allowed to exchange.
}
but if I add roles to the token in step 7 ( add --data-urlencode 'scope=roles') then everything works.
In reply to @dreamcrash Thanks for the detailed analysis! I solved my problem in a slightly different way - I left roles in Client Scopes optional, made two mappers (for client roles and realm roles) - in which I specified that realm roles should be added to the access token, but client roles only to /userinfo. Since moderators are not expected to have any additional roles from realm-management other than impersonate - only it is added to the token.