ID token mapping

This commit is contained in:
Bill Burke 2015-03-04 18:39:10 -05:00
parent 51e2507f5d
commit 453ef808cc
3 changed files with 43 additions and 39 deletions

View file

@ -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<String, String> error = new HashMap<String, String>();
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();

View file

@ -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,7 +238,7 @@ public class TokenManager {
}
}
public AccessToken transformToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
UserSessionModel userSession, ClientSessionModel clientSession) {
Set<ProtocolMapperModel> mappings = client.getProtocolMappers();
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
@ -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<ProtocolMapperModel> 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;
}

View file

@ -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())