role name mapper
This commit is contained in:
parent
28a5e61dff
commit
451ce64907
4 changed files with 46 additions and 21 deletions
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
) {
|
) {
|
||||||
|
|
Loading…
Reference in a new issue