diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java index 5e4080976f..5bcc03130e 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java @@ -339,7 +339,7 @@ public class OIDCLoginProtocolService { TokenManager.attachClientSession(userSession, clientSession); - AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event) + AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSession) .generateAccessToken(session, scope, client, user, userSession, clientSession) .generateRefreshToken() .generateIDToken() @@ -506,9 +506,9 @@ public class OIDCLoginProtocolService { event.error(Errors.INVALID_TOKEN); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); } - AccessToken accessToken; + AccessTokenResponse res; try { - accessToken = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event); + res = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event); } catch (OAuthErrorException e) { Map error = new HashMap(); error.put(OAuth2Constants.ERROR, e.getError()); @@ -517,10 +517,6 @@ public class OIDCLoginProtocolService { return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); } - AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event) - .accessToken(accessToken) - .generateIDToken() - .generateRefreshToken().build(); event.success(); @@ -680,7 +676,7 @@ public class OIDCLoginProtocolService { return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); } - AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event) + AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSession) .accessToken(token) .generateIDToken() .generateRefreshToken().build(); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java index 55a78da71f..14fb6ec32f 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java @@ -22,6 +22,7 @@ import org.keycloak.models.UserSessionProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.ProtocolMapper; import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper; +import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.IDToken; @@ -58,7 +59,7 @@ public class TokenManager { } } - public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel client, String encodedRefreshToken, EventBuilder event) throws OAuthErrorException { + public AccessTokenResponse refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel client, String encodedRefreshToken, EventBuilder event) throws OAuthErrorException { RefreshToken refreshToken = verifyRefreshToken(realm, encodedRefreshToken); event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()); @@ -105,11 +106,15 @@ public class TokenManager { AccessToken accessToken = initToken(realm, client, user, userSession, clientSession); accessToken.setRealmAccess(refreshToken.getRealmAccess()); accessToken.setResourceAccess(refreshToken.getResourceAccess()); - accessToken = transformToken(session, accessToken, realm, client, user, userSession, clientSession); + accessToken = transformAccessToken(session, accessToken, realm, client, user, userSession, clientSession); userSession.setLastSessionRefresh(currentTime); - return accessToken; + AccessTokenResponse res = responseBuilder(realm, client, event, session, userSession, clientSession) + .accessToken(accessToken) + .generateIDToken() + .generateRefreshToken().build(); + return res; } public RefreshToken verifyRefreshToken(RealmModel realm, String encodedRefreshToken) throws OAuthErrorException { @@ -138,7 +143,7 @@ public class TokenManager { for (RoleModel role : requestedRoles) { addComposites(token, role); } - token = transformToken(session, token, realm, client, user, userSession, clientSession); + token = transformAccessToken(session, token, realm, client, user, userSession, clientSession); return token; } @@ -233,8 +238,8 @@ public class TokenManager { } } - public AccessToken transformToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user, - UserSessionModel userSession, ClientSessionModel clientSession) { + public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user, + UserSessionModel userSession, ClientSessionModel clientSession) { Set mappings = client.getProtocolMappers(); KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (ProtocolMapperModel mapping : mappings) { @@ -249,6 +254,21 @@ public class TokenManager { } return token; } + public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user, + UserSessionModel userSession, ClientSessionModel clientSession) { + Set mappings = client.getProtocolMappers(); + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + for (ProtocolMapperModel mapping : mappings) { + if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue; + + ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); + if (mapper == null || !(mapper instanceof OIDCIDTokenMapper)) continue; + token = ((OIDCIDTokenMapper)mapper).transformIDToken(token, mapping, session, userSession, clientSession); + + + + } + } protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) { @@ -308,22 +328,29 @@ public class TokenManager { return encodedToken; } - public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event) { - return new AccessTokenResponseBuilder(realm, client, event); + public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) { + return new AccessTokenResponseBuilder(realm, client, event, session, userSession, clientSession); } public class AccessTokenResponseBuilder { RealmModel realm; ClientModel client; + EventBuilder event; + KeycloakSession session; + UserSessionModel userSession; + ClientSessionModel clientSession; + AccessToken accessToken; RefreshToken refreshToken; IDToken idToken; - EventBuilder event; - public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event) { + public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) { this.realm = realm; this.client = client; this.event = event; + this.session = session; + this.userSession = userSession; + this.clientSession = clientSession; } public AccessTokenResponseBuilder accessToken(AccessToken accessToken) { @@ -366,25 +393,7 @@ public class TokenManager { if (realm.getAccessTokenLifespan() > 0) { idToken.expiration(Time.currentTime() + realm.getAccessTokenLifespan()); } - idToken.getUserClaimSet().setPreferredUsername(accessToken.getUserClaimSet().getPreferredUsername()); - idToken.getUserClaimSet().setGivenName(accessToken.getUserClaimSet().getGivenName()); - idToken.getUserClaimSet().setMiddleName(accessToken.getUserClaimSet().getMiddleName()); - idToken.getUserClaimSet().setFamilyName(accessToken.getUserClaimSet().getFamilyName()); - idToken.getUserClaimSet().setName(accessToken.getUserClaimSet().getName()); - idToken.getUserClaimSet().setNickName(accessToken.getUserClaimSet().getNickName()); - idToken.getUserClaimSet().setGender(accessToken.getUserClaimSet().getGender()); - idToken.getUserClaimSet().setPicture(accessToken.getUserClaimSet().getPicture()); - idToken.getUserClaimSet().setProfile(accessToken.getUserClaimSet().getProfile()); - idToken.getUserClaimSet().setWebsite(accessToken.getUserClaimSet().getWebsite()); - idToken.getUserClaimSet().setBirthdate(accessToken.getUserClaimSet().getBirthdate()); - idToken.getUserClaimSet().setEmail(accessToken.getUserClaimSet().getEmail()); - idToken.getUserClaimSet().setEmailVerified(accessToken.getUserClaimSet().getEmailVerified()); - idToken.getUserClaimSet().setLocale(accessToken.getUserClaimSet().getLocale()); - idToken.getUserClaimSet().setAddress(accessToken.getUserClaimSet().getAddress()); - idToken.getUserClaimSet().setPhoneNumber(accessToken.getUserClaimSet().getPhoneNumber()); - idToken.getUserClaimSet().setPhoneNumberVerified(accessToken.getUserClaimSet().getPhoneNumberVerified()); - idToken.getUserClaimSet().setZoneinfo(accessToken.getUserClaimSet().getZoneinfo()); - idToken.setOtherClaims(accessToken.getOtherClaims()); + transformIDToken(session, idToken, realm, client, userSession.getUser(), userSession, clientSession); return this; } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java index c96b9f194a..9958ae0b3a 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java @@ -31,7 +31,6 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.representations.AccessToken; -import org.keycloak.representations.UserClaimSet; import org.keycloak.services.managers.AppAuthManager; import org.keycloak.services.managers.EventsManager; import org.keycloak.services.resources.Cors; @@ -133,7 +132,7 @@ public class UserInfoService { ClientModel clientModel = realmModel.findClient(accessToken.getIssuedFor()); UserModel userModel = userSession.getUser(); AccessToken userInfo = new AccessToken(); - this.tokenManager.transformToken(session, userInfo, realmModel, clientModel, userModel, userSession, null); + this.tokenManager.transformAccessToken(session, userInfo, realmModel, clientModel, userModel, userSession, null); event .detail(Details.USERNAME, userModel.getUsername())