Add roles based on attribute value (instead of role name) #86
3 changed files with 75 additions and 2 deletions
|
@ -74,6 +74,20 @@ public class RegexRealmAndClientRoleClaimMapper extends AbstractClaimMapper {
|
|||
realmRolesRegularExpressionConfigProperty.setHelpText("regular expression to apply to the OIDC claim to extract realm roles; must specify one named-capturing groups: role");
|
||||
realmRolesRegularExpressionConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(realmRolesRegularExpressionConfigProperty);
|
||||
|
||||
ProviderConfigProperty searchRolesAttributeNameAttributeNameConfigProperty = new ProviderConfigProperty();
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setName(RegexRealmAndClientRoleMapperUtil.SEARCH_ROLES_ATTRIBUTE_NAME);
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setLabel("search roles attribute name");
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setHelpText("only evaluate realm or client roles having an attribute with this name");
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(searchRolesAttributeNameAttributeNameConfigProperty);
|
||||
|
||||
ProviderConfigProperty searchRolesAttributeNameRegularExpressionConfigProperty = new ProviderConfigProperty();
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setName(RegexRealmAndClientRoleMapperUtil.SEARCH_ROLES_REGULAR_EXPRESSION);
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setLabel("search roles regular expression");
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setHelpText("regular expression to apply to the OIDC claim to search for roles having this attribute value; must specify one named-capturing groups: value");
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(searchRolesAttributeNameRegularExpressionConfigProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -74,6 +74,20 @@ public class RegexRealmAndClientRoleAttributeMapper extends AbstractIdentityProv
|
|||
realmRolesRegularExpressionConfigProperty.setHelpText("regular expression to apply to the SAML attribute to extract realm roles; must specify one named-capturing group: role");
|
||||
realmRolesRegularExpressionConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(realmRolesRegularExpressionConfigProperty);
|
||||
|
||||
ProviderConfigProperty searchRolesAttributeNameAttributeNameConfigProperty = new ProviderConfigProperty();
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setName(RegexRealmAndClientRoleMapperUtil.SEARCH_ROLES_ATTRIBUTE_NAME);
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setLabel("search roles attribute name");
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setHelpText("only evaluate realm or client roles having an attribute with this name");
|
||||
searchRolesAttributeNameAttributeNameConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(searchRolesAttributeNameAttributeNameConfigProperty);
|
||||
|
||||
ProviderConfigProperty searchRolesAttributeNameRegularExpressionConfigProperty = new ProviderConfigProperty();
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setName(RegexRealmAndClientRoleMapperUtil.SEARCH_ROLES_REGULAR_EXPRESSION);
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setLabel("search roles regular expression");
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setHelpText("regular expression to apply to the SAML claim to search for roles having this attribute value; must specify one named-capturing groups: value");
|
||||
searchRolesAttributeNameRegularExpressionConfigProperty.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(searchRolesAttributeNameRegularExpressionConfigProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.google.common.collect.Sets;
|
|||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.models.ClientModel;
|
||||
|
@ -27,6 +28,10 @@ public final class RegexRealmAndClientRoleMapperUtil {
|
|||
|
||||
public static final String REALM_ROLES_REGULAR_EXPRESSION = "realm-roles-regular-expression";
|
||||
|
||||
public static final String SEARCH_ROLES_ATTRIBUTE_NAME = "search-roles-attribute-name";
|
||||
|
||||
public static final String SEARCH_ROLES_REGULAR_EXPRESSION = "search-roles-regular-expression";
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(RegexRealmAndClientRoleMapperUtil.class);
|
||||
|
||||
private RegexRealmAndClientRoleMapperUtil() {
|
||||
|
@ -39,12 +44,20 @@ public final class RegexRealmAndClientRoleMapperUtil {
|
|||
// adjust the user's client role assignments
|
||||
String clientRolesRegularExpression = mapper.getConfig().getOrDefault(CLIENT_ROLES_REGULAR_EXPRESSION, "");
|
||||
String clientRolesAttributeName = mapper.getConfig().getOrDefault(CLIENT_ROLES_ATTRIBUTE_NAME, "");
|
||||
if(clientRolesRegularExpression != "" && clientRolesAttributeName != "")
|
||||
RegexRealmAndClientRoleMapperUtil.adjustUserClientRoleAssignments(realm, user, assertedValues, clientRolesRegularExpression, clientRolesAttributeName);
|
||||
|
||||
// adjust the user's realm role assignments
|
||||
String realmRolesRegularExpression = mapper.getConfig().getOrDefault(REALM_ROLES_REGULAR_EXPRESSION, "");
|
||||
String realmRolesAttributeName = mapper.getConfig().getOrDefault(REALM_ROLES_ATTRIBUTE_NAME, "");
|
||||
if(realmRolesRegularExpression != "" && realmRolesRegularExpression != "")
|
||||
RegexRealmAndClientRoleMapperUtil.adjustUserRealmRoleAssignments(realm, user, assertedValues, realmRolesRegularExpression, realmRolesAttributeName);
|
||||
|
||||
// adjust the user's attribute-based (search) role assignments
|
||||
String searchRolesRegularExpression = mapper.getConfig().getOrDefault(SEARCH_ROLES_REGULAR_EXPRESSION, "");
|
||||
String searchRolesAttributeName = mapper.getConfig().getOrDefault(SEARCH_ROLES_ATTRIBUTE_NAME, "");
|
||||
if(searchRolesRegularExpression != "" && searchRolesAttributeName != "")
|
||||
RegexRealmAndClientRoleMapperUtil.adjustUserSearchRoleAssignments(realm, user, assertedValues, searchRolesRegularExpression, searchRolesAttributeName);
|
||||
}
|
||||
|
||||
private static void adjustUserClientRoleAssignments(RealmModel realm, UserModel user, Set<String> assertedValues, String regularExpression, String attributeName) {
|
||||
|
@ -110,4 +123,36 @@ public final class RegexRealmAndClientRoleMapperUtil {
|
|||
// un-assign the realm roles that the user has but shouldn't
|
||||
Sets.difference(haveRoles, wantRoles).forEach(user::deleteRoleMapping);
|
||||
}
|
||||
|
||||
private static void adjustUserSearchRoleAssignments(RealmModel realm, UserModel user, Set<String> assertedValues, String regularExpression, String attributeName) {
|
||||
LOG.trace("adjust user attribute-based role assignments");
|
||||
|
||||
Pattern pattern = Pattern.compile(regularExpression);
|
||||
|
||||
// determine the roles that the user should have
|
||||
Set<RoleModel> wantRoles = assertedValues.stream()
|
||||
.map(pattern::matcher)
|
||||
.filter(Matcher::matches)
|
||||
.filter(matcher -> matcher.groupCount() == 1)
|
||||
.filter(matcher -> matcher.group("value") != null)
|
||||
.flatMap(matcher ->
|
||||
realm.getRolesStream()
|
||||
.filter(realmRole ->
|
||||
realmRole.getAttributeStream(attributeName)
|
||||
.flatMap(s -> Stream.of(s.split(",")))
|
||||
.anyMatch(s -> matcher.group("value").equals(s))))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// determine the roles that the user does have
|
||||
Set<RoleModel> haveRoles = user.getRoleMappingsStream()
|
||||
.filter(role -> role.getAttributes().containsKey(attributeName))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// assign the roles that the user should have but doesn't
|
||||
Sets.difference(wantRoles, haveRoles).forEach(user::grantRole);
|
||||
|
||||
// un-assign the roles that the user has but shouldn't
|
||||
Sets.difference(haveRoles, wantRoles).forEach(user::deleteRoleMapping);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue