'KeyCloak Refresh External IDP Token
We are using KeyCloak Identity Brokering to federate authentication to an external IDP. The Identity Provider is of type OpenID Connect v1.0. Additionally, we are using OIDC Authorization Code Flow with PKCE.
We are successully able to retrieve the tokens from the external IDP based on the following documentation: https://www.keycloak.org/docs/latest/server_admin/#retrieving-external-idp-tokens
However, when the KeyCloak token is refreshed using "refresh_token" grant by the user-agent, the tokens from the external IDP are not. There is very little documentation available from KeyCloak on this topic.
Does anyone know how to refresh the tokens from the external IDP ?
Update: I have opened an issue with KeyCloak community https://github.com/keycloak/keycloak-community/issues/277
Solution 1:[1]
Keycloak retains both the access token and refresh token from the upstream IdP. When you perform a token exchange it will refresh the tokens if the access token has expired but the refresh token has not, seen here: https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java#L186-L187
The long-and-short of it is you need to call the token exchange endpoint more often than the external refresh token expires. Depending on your implementation you can take advantage of this in a number of ways. For example, I've set my access token ttl shorter than the external IdP's refresh token ttl and I've got a confidential client that calls the token exchange endpoint every time it sees a new access token, it isn't the best possible solution but it's better than a sharp stick in the eye.
I don't know why the Keycloak developers don't just refresh any external token when you perform a token refresh of your Keycloak-minted token. They're smart people, so I'm sure there's a reason, but thus far I haven't been able to figure it out. I've been considering extending the existing OIDCIdentityProvider to do just that but I'd rather not open that can of worms until I understand what I'm getting into. If anyone has any insight I'd appreciate it.
Solution 2:[2]
The solution proposed by @Hawk refers to a different API - Token Exchange - which can be used to retrieve (or even forge) tokens on KeyCloak. Among all different tokens you can exchange, you can retrieve tokens from configured Identity Providers, and is what we ended up using in the end.
Long story short, the "Retrieving external IDP tokens" functionality you are using will not refresh the token for you: if you plan to use it, you'll have to retrieve the refresh token and generate a new access token yourself, which is unfortunate as this would force you to have the client/secret ids of the Identity Provider on your application.
The Token Exchange API will instead refresh the token for you. You can easily retrieve the IP access token by issuing this request (the example uses python, you can obviously use any other language):
response = requests.post(
f"{ID_PROVIDER_HOST}/auth/realms/{REALM}/protocol/openid-connect/token",
data={
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"requested_issuer": IDENTITY_PROVIDER_ALIAS,
"subject_token": access_token,
},
)
You need some configuration, though: first of all, Token Exchange is in "Technology Preview" as of current KeyCloak version (17), and is not enabled by default; refer to the KeyCloak documentation to see how to enable it.
Then, you'll need to enable your client to exchange IP tokens: from the administration panel of your realm:
- select "Identity Providers" from the sidebar;
- select the identity provider you want to retrieve the token from;
- select the "Permissions" tab;
- enable permissions, if not already enabled;
- click on "token exchange"
- in the "Apply Policy" table select "Create Policy" of type "Client"
- give the policy a name, and select the client you want to be able to retrieve the access tokens.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | micpap25 |
| Solution 2 | StefanoP |
