I’m trying to impersonate a user using the token exchange functionality but I always get the error that the client is not allowed to exchange.
This is the request I’m doing using the WebFlux WebClient:
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("grant_type", "urn:ietf:params:oauth:grant-type:token-exchange");
formData.add("requested_token_type", "urn:ietf:params:oauth:token-type:access_token");
formData.add("client_id", keycloakClientId);
formData.add("requested_subject", userId);
formData.add("subject_token", token);
return WebClient.create()
.post()
.uri(authServerUrl + "/realms/" + authServerRealm + "/protocol/openid-connect/token")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(formData))
.exchangeToMono(clientResponse -> clientResponse.bodyToMono(AccessTokenResponse.class));
The response I get is this one:
{"error":"access_denied","error_description":"Client not allowed to exchange"}
How do I get the token above to be exchanged:
KeycloakBuilder.builder()
.serverUrl(authServerUrl)
.realm(authServerRealm)
.grantType(OAuth2Constants.PASSWORD)
.username(keycloakAdminUsername)
.password(keycloakAdminPassword)
.clientId(keycloakClientId)
.build();
What I am doing wrong? Why does the client need to be allowed to exchange since this impersonation and not client token exchange. Does the client need to be confidential for this to be done?
You need to grant permission (on the target client) to allow keycloakClientId to mint a token for the target client.
7.1.1 in the docs:
https://www.keycloak.org/docs/latest/securing_apps/#internal-token-to-internal-token-exchange
You will also need to start keycloak with the following flags, so that you enable fine grained permissions:
-Dkeycloak.profile.feature.admin_fine_grained_authz=enabled -Dkeycloak.profile.feature.token_exchange=enabled
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With