Hello everyone,
I need some help understanding how token exchange works in Keycloak. I’ve spent several hours trying to solve an issue and would appreciate any guidance.
I’m running Keycloak 26.6.3.
One thing that has made troubleshooting difficult is that most of the documentation, blog posts, and tutorials I found online seem to refer to older Keycloak versions. They often mention configuration screens, permissions, or settings that appear to no longer exist in the current version, so I’m not sure which guidance is still applicable.
I’m attempting to perform an external-to-internal token exchange. My setup is as follows:
- I generate an access token from a local Authentik server.
- I want to exchange that token for a Keycloak token using the Token Exchange grant.
However, when I send the POST request to Keycloak, I receive the following error:
{
"error": "access_denied",
"error_description": "Client not allowed to exchange"
}
The relevant Keycloak log entry is:
2026-06-14 03:59:35,925 TRACE [org.keycloak.events] (executor-thread-1)
type="TOKEN_EXCHANGE_ERROR",
realmId="37adc7b3-4301-4d19-b7c3-915f358fa904",
realmName="dakar",
clientId="mcp-server",
userId="null",
ipAddress="192.168.65.1",
error="not_allowed",
reason="client not allowed to exchange subject_issuer",
auth_method="token_exchange",
grant_type="urn:ietf:params:oauth:grant-type:token-exchange",
subject_issuer="http://localhost:9000/application/o/app/",
client_auth_method="client-secret",
requestUri="http://localhost:8080/realms/dakar/protocol/openid-connect/token"
What confuses me is the message:
client not allowed to exchange subject_issuer
From my understanding, this suggests that Keycloak is rejecting the external issuer (subject_issuer), but I’m not sure which configuration is missing.
Could someone explain what permissions or client configuration are required to allow an external Authentik issuer to participate in token exchange on Keycloak 26.6.3?
Is there a specific Token Exchange permission, Identity Provider configuration, client policy, or trusted issuer configuration that must be enabled?
Thanks in advance for any help!