I have a public client app
from which I obtained the access token of a user via standard flow.
I now want to obtain a token for the confidential client bridge
of the same user (sub = same user ID).
I tried following https://www.keycloak.org/securing-apps/token-exchange#_internal_internal_making_request but it's sadly very ambiguously worded in some places.
My current request always gives me Invalid token
.
The request:
curl --location 'https://example.com/keycloak/realms/test/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=<app token>' \
--data-urlencode 'requested_token_type=urn:ietf:params:oauth:token-type:access_token' \
--data-urlencode 'audience=bridge' \
--data-urlencode 'client_id=app'
Since it's a public client, there is no client secret.
The manual only says that public clients are not allowed to perform token exchanges using tokens from other clients
but the token is from the client app
itself or is there a comma missing and it means a public client cannot exchange for other clients using a token in general?
My goal is just to trade down to a token with less permissions. But if the public client can only trade for other tokens of itself, how do I strip permissions from the resulting token?
Edit: I also added the bridge client to the audience field of the app user token, but sill no luck.
Usually in token exchange the main goal is one of the following and the token exchange request should include a scope
parameter that represents something like a business area.
Downscoping - to reduce token scopes so that the target API does not receive the client's full access token. This is the most common case.
Upscoping - to call upstream APIs with scopes that you don't want the original client to have a relationship with. This should not be used if it operates outside user consent.
The client must be authorized to:
Use token exchange
Use any scopes requested, including for upscoping
The authorization server may deny certain operations, like upscoping, for public clients
Most commonly, token exchange is done by backend conponents, like an API gateway or an API. Before calling the upstream they replace the original token in the HTTP authorization header with the exchanged token. Therefore, this type of backend component must be registered as an OAuth client with the token exchange capability and scopes.
In your case I think an approach of the following kind, where you rule out causes one by one will help you understand Keycloak specific logic:
First find the error cause in Keycloak logs - if required, change the log level eg to DEBUG.
Change client permissions according to Keycloak docs, to grant token exchange permissions.
Temporarily configure a client secret to see if that makes a difference. If so you may need to redesign deployments, eg to make an API gateway or entry point API do the token exchange.