role name mapper

This commit is contained in:
Bill Burke 2015-03-11 09:59:56 -04:00
parent 28a5e61dff
commit 451ce64907
4 changed files with 46 additions and 21 deletions

View file

@ -3,6 +3,7 @@ package org.keycloak.protocol;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.representations.AccessToken;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
@ -41,4 +42,18 @@ public class ProtocolMapperUtils {
} }
return null; return null;
} }
public static String[] parseRole(String role) {
int scopeIndex = role.indexOf('.');
if (scopeIndex > -1) {
String appName = role.substring(0, scopeIndex);
role = role.substring(scopeIndex + 1);
String[] rtn = {appName, role};
return rtn;
} else {
String[] rtn = {null, role};
return rtn;
}
}
} }

View file

@ -4,6 +4,7 @@ import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
@ -65,12 +66,11 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) { UserSessionModel userSession, ClientSessionModel clientSession) {
String role = mappingModel.getConfig().get(ROLE_CONFIG); String role = mappingModel.getConfig().get(ROLE_CONFIG);
String appName = null; String[] scopedRole = ProtocolMapperUtils.parseRole(role);
int scopeIndex = role.indexOf('.'); String appName = scopedRole[0];
if (scopeIndex > -1) { String roleName = scopedRole[1];
appName = role.substring(0, scopeIndex); if (appName != null) {
role = role.substring(scopeIndex + 1); token.addAccess(appName).addRole(roleName);
token.addAccess(appName).addRole(role);
} else { } else {
AccessToken.Access access = token.getRealmAccess(); AccessToken.Access access = token.getRealmAccess();
if (access == null) { if (access == null) {

View file

@ -76,29 +76,35 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
UserSessionModel userSession, ClientSessionModel clientSession) { UserSessionModel userSession, ClientSessionModel clientSession) {
String role = mappingModel.getConfig().get(ROLE_CONFIG); String role = mappingModel.getConfig().get(ROLE_CONFIG);
String newName = mappingModel.getConfig().get(NEW_ROLE_NAME); String newName = mappingModel.getConfig().get(NEW_ROLE_NAME);
String appName = null;
int scopeIndex = role.indexOf('.'); String[] scopedRole = ProtocolMapperUtils.parseRole(role);
if (scopeIndex > -1) { String[] newScopedRole = ProtocolMapperUtils.parseRole(newName);
appName = role.substring(0, scopeIndex); String appName = scopedRole[0];
String roleName = scopedRole[1];
if (appName != null) {
AccessToken.Access access = token.getResourceAccess(appName); AccessToken.Access access = token.getResourceAccess(appName);
if (access == null) return token; if (access == null) return token;
if (!access.getRoles().contains(roleName)) return token;
role = role.substring(scopeIndex + 1); access.getRoles().remove(roleName);
if (!access.getRoles().contains(role)) return token;
access.getRoles().remove(role);
} else { } else {
AccessToken.Access access = token.getRealmAccess(); AccessToken.Access access = token.getRealmAccess();
if (access == null) return token; if (access == null) return token;
access.getRoles().remove(role); access.getRoles().remove(roleName);
} }
String newAppName = null; String newAppName = newScopedRole[0];
scopeIndex = newName.indexOf('.'); String newRoleName = newScopedRole[1];
if (scopeIndex > -1) { AccessToken.Access access = null;
newAppName = role.substring(0, scopeIndex); if (newAppName == null) {
newName = role.substring(scopeIndex + 1); access = token.getRealmAccess();
token.addAccess(newAppName).addRole(newName); if (access == null) {
access = new AccessToken.Access();
token.setRealmAccess(access);
} }
} else {
access = token.addAccess(newAppName);
}
access.addRole(newRoleName);
return token; return token;
} }

View file

@ -607,6 +607,7 @@ public class AccessTokenTest {
app.addProtocolMapper(UserAttributeMapper.createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true)); app.addProtocolMapper(UserAttributeMapper.createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true));
app.addProtocolMapper(HardcodedRole.create("hard-realm", "hardcoded")); app.addProtocolMapper(HardcodedRole.create("hard-realm", "hardcoded"));
app.addProtocolMapper(HardcodedRole.create("hard-app", "app.hardcoded")); app.addProtocolMapper(HardcodedRole.create("hard-app", "app.hardcoded"));
app.addProtocolMapper(RoleNameMapper.create("rename-app-role", "test-app.customer-user", "realm-user"));
session.getTransaction().commit(); session.getTransaction().commit();
session.close(); session.close();
} }
@ -647,6 +648,8 @@ public class AccessTokenTest {
nested = (Map)accessToken.getOtherClaims().get("home"); nested = (Map)accessToken.getOtherClaims().get("home");
Assert.assertEquals("617-777-6666", nested.get("phone")); Assert.assertEquals("617-777-6666", nested.get("phone"));
Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded")); Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
Assert.assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
Assert.assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded")); Assert.assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
@ -665,6 +668,7 @@ public class AccessTokenTest {
|| model.getName().equals("hard-nested") || model.getName().equals("hard-nested")
|| model.getName().equals("custom phone") || model.getName().equals("custom phone")
|| model.getName().equals("nested phone") || model.getName().equals("nested phone")
|| model.getName().equals("rename-app-role")
|| model.getName().equals("hard-realm") || model.getName().equals("hard-realm")
|| model.getName().equals("hard-app") || model.getName().equals("hard-app")
) { ) {