diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index 54878296e3..005f6a6416 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -72,6 +72,7 @@ import org.keycloak.protocol.oidc.utils.RedirectUtils; import org.keycloak.protocol.saml.SamlSessionUtils; import org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor; import org.keycloak.representations.AccessToken; +import org.keycloak.representations.AccessTokenResponse; import org.keycloak.services.ErrorPage; import org.keycloak.services.ErrorPageException; import org.keycloak.services.ErrorResponse; @@ -1095,12 +1096,31 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal private void updateToken(BrokeredIdentityContext context, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel) { if (context.getIdpConfig().isStoreToken() && !ObjectUtil.isEqualOrBothNull(context.getToken(), federatedIdentityModel.getToken())) { - federatedIdentityModel.setToken(context.getToken()); + try { + // like in OIDCIdentityProvider.exchangeStoredToken() + // we shouldn't override the refresh token if it is null in the context and not null in the DB + // as for google IDP it will be lost forever + if (federatedIdentityModel.getToken() != null) { + AccessTokenResponse previousResponse = JsonSerialization.readValue(federatedIdentityModel.getToken(), AccessTokenResponse.class); + AccessTokenResponse newResponse = JsonSerialization.readValue(context.getToken(), AccessTokenResponse.class); - this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel); + if (newResponse.getRefreshToken() == null && previousResponse.getRefreshToken() != null) { + newResponse.setRefreshToken(previousResponse.getRefreshToken()); + newResponse.setRefreshExpiresIn(previousResponse.getRefreshExpiresIn()); + } - if (isDebugEnabled()) { - logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias()); + federatedIdentityModel.setToken(JsonSerialization.writeValueAsString(newResponse)); + } else { + federatedIdentityModel.setToken(context.getToken()); + } + + this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel); + + if (isDebugEnabled()) { + logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias()); + } + } catch (IOException e) { + throw new RuntimeException(e); } } }