From eed591f0b9d6fe89c0183d003e75017b085a1ce6 Mon Sep 17 00:00:00 2001 From: lx277856602 Date: Mon, 6 Apr 2026 09:51:03 +0800 Subject: [PATCH] Fix: Auto-refresh external IDP tokens before returning (fixes #14644) - Add token expiration check in retrieveToken V2 API method - Automatically refresh expired tokens using refresh_token if available - Update stored token with new access/refresh token pair - Handle refresh failures gracefully (log warning, continue with existing token) This fix ensures that the V2 API endpoint /realms/{realm}/broker/{provider_alias}/token automatically refreshes expired external IDP tokens before returning them, consistent with the behavior of the V1 API method. Fixes: https://github.com/keycloak/keycloak/issues/14644 --- .../oidc/AbstractOAuth2IdentityProvider.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java index bd8c45ffadd..f044015943a 100755 --- a/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java +++ b/services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java @@ -324,6 +324,27 @@ public abstract class AbstractOAuth2IdentityProvider 0) { + long accessTokenExpiration = Time.currentTime() + newResponse.getExpiresIn(); + newResponse.setAccessTokenExpiration(accessTokenExpiration); + } + model.setToken(JsonSerialization.writeValueAsString(newResponse)); + session.users().updateFederatedIdentity(session.getContext().getRealm(), user, model); + } + } catch (IOException e) { + logger.warnf(e, "Unable to refresh token for user %s and provider %s", user.getId(), getConfig().getAlias()); + // Continue with existing token if refresh fails + } + } response = exchangeStoredToken(uriInfo, null, null, userSession, user); }