Apologies if this is already documented, but I’m still cannot find anywhere how to allow for the following scenario, which in my opinion must be quite a normal requirement.
I’m running Keycloak in Docker with the extra parameters:
-Dkeycloak.profile.feature.token_exchange=enabled
-Dkeycloak.profile.feature.admin_fine_grained_authz=enabled
We want to have all our super-users (administrators and support personnel) in the master realm. This works fine from within the Keycloak UI, using the impersonate button, but I have no luck with the token exchange API.
Via the token exchange functionality, we want to exchange a token from the master realm for an access token for the acme realm and the acme-client
Login super-user:
token=$(curl -s -d 'client_id=security-admin-console' -d 'username=admin' -d
'password=superpassword' -d 'grant_type=password'
'https://keycloak.example.net/auth/realms/master/protocol/openid-connect/token' | jq -r
.access_token)
Attempt to exchange token for one in acme realm with acme-client:
curl -s -X POST "https://keycloak.example.net/auth/realms/acme/protocol/openid-connect/token" \
--data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d 'client_id=acme-client' \
-d "requested_subject=acme-user" \
-d "subject_token=$token" \
--data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token"
This gives me an error that my token is invalid.
I then tried to set up the master realm as an identity provider with alias master and added to this parameter to the above request:
-d "subject_issuer=master"
This gives me:
{“error”:“access_denied”,“error_description”:“Client not allowed to exchange”}
I then started searching for issues regarding this, and I found that I needed to enable fine-grained authz and set up a security policy. I cannot find that this makes any difference, and I thought the point was that fine-grained was not cross-realm anyway.
I would be extremely grateful if anyone could provide me with any hint to what I’m missing, a better way of achieving this functionality, or even better a minimalist example. I find other questions resembling this one, but there are no answers, unfortunately.