keycloak-aplcache

Merge pull request #1963 from mposolda/master KEYCLOAK-1899

12/22/2015 5:43:09 PM

Changes

Details

diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
index 309e26a..6f0b02a 100755
--- a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java
@@ -1,14 +1,11 @@
 package org.keycloak.broker.provider;
 
-import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
-import org.keycloak.broker.provider.BrokeredIdentityContext;
-import org.keycloak.broker.provider.IdentityBrokerException;
-import org.keycloak.models.ClientModel;
 import org.keycloak.models.IdentityProviderMapperModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ProviderConfigProperty;
 
 import java.util.ArrayList;
@@ -20,7 +17,7 @@ import java.util.List;
  */
 public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
     public static final String ROLE = "role";
-    protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+    protected static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
 
     static {
         ProviderConfigProperty property;
@@ -32,34 +29,6 @@ public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
         configProperties.add(property);
     }
 
-
-
-    public static String[] parseRole(String role) {
-        int scopeIndex = role.lastIndexOf('.');
-        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;
-
-        }
-    }
-
-    public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
-        String[] parsedRole = parseRole(roleName);
-        RoleModel role = null;
-        if (parsedRole[0] == null) {
-            role = realm.getRole(parsedRole[1]);
-        } else {
-            ClientModel client = realm.getClientByClientId(parsedRole[0]);
-            role = client.getRole(parsedRole[1]);
-        }
-        return role;
-    }
-
     @Override
     public List<ProviderConfigProperty> getConfigProperties() {
         return configProperties;
@@ -93,7 +62,7 @@ public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
     @Override
     public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
         String roleName = mapperModel.getConfig().get(ROLE);
-        RoleModel role = getRoleFromString(realm, roleName);
+        RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
         if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
         user.grantRole(role);
     }
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
index b3bd191..2d79a5b 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java
@@ -10,6 +10,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ProviderConfigProperty;
 
 import java.util.ArrayList;
@@ -80,7 +81,7 @@ public class ClaimToRoleMapper extends AbstractClaimMapper {
     public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
         String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
         if (hasClaimValue(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
             if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
             user.grantRole(role);
         }
@@ -90,7 +91,7 @@ public class ClaimToRoleMapper extends AbstractClaimMapper {
     public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
         String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
         if (!hasClaimValue(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
             if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
             user.deleteRoleMapping(role);
         }
diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
index e4e0de0..f7ddb76 100755
--- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
+++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java
@@ -11,6 +11,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.JsonWebToken;
 
@@ -85,7 +86,7 @@ public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
         JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
         //if (token == null) return;
         String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
-        String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
+        String[] parseRole = KeycloakModelUtils.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
         String externalRoleName = parseRole[1];
         String claimName = null;
         if (parseRole[0] == null) {
@@ -95,7 +96,7 @@ public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
         }
         Object claim = getClaimValue(token, claimName);
         if (valueEquals(externalRoleName, claim)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
             if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
             return role;
         }
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
index 4014a9a..48d2ac8 100755
--- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java
@@ -15,6 +15,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.JsonWebToken;
 
@@ -95,7 +96,7 @@ public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
     public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
         String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
         if (isAttributePresent(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
             if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
             user.grantRole(role);
         }
@@ -125,7 +126,7 @@ public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
     public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
         String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
         if (!isAttributePresent(mapperModel, context)) {
-            RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
+            RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
             if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
             user.deleteRoleMapping(role);
         }
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapperFactory.java
index e08429e..7fbcf06 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapperFactory.java
@@ -75,7 +75,7 @@ public class FullNameLDAPFederationMapperFactory extends AbstractLDAPFederationM
     }
 
     @Override
-    public void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
+    public void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
         checkMandatoryConfigAttribute(FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE, "LDAP Full Name Attribute", mapperModel);
     }
 
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapper.java
new file mode 100644
index 0000000..866d2b1
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapper.java
@@ -0,0 +1,109 @@
+package org.keycloak.federation.ldap.mappers;
+
+import java.util.Set;
+
+import org.jboss.logging.Logger;
+import org.keycloak.federation.ldap.LDAPFederationProvider;
+import org.keycloak.federation.ldap.idm.model.LDAPObject;
+import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.models.utils.UserModelDelegate;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HardcodedLDAPRoleMapper extends AbstractLDAPFederationMapper {
+
+    private static final Logger logger = Logger.getLogger(HardcodedLDAPRoleMapper.class);
+
+    public static final String ROLE = "role";
+
+    public HardcodedLDAPRoleMapper(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, RealmModel realm) {
+        super(mapperModel, ldapProvider, realm);
+    }
+
+    @Override
+    public void beforeLDAPQuery(LDAPQuery query) {
+    }
+
+    @Override
+    public UserModel proxy(LDAPObject ldapUser, UserModel delegate) {
+        return new UserModelDelegate(delegate) {
+
+            @Override
+            public Set<RoleModel> getRealmRoleMappings() {
+                Set<RoleModel> roles = super.getRealmRoleMappings();
+
+                RoleModel role = getRole();
+                if (role != null && role.getContainer().equals(realm)) {
+                    roles.add(role);
+                }
+
+                return roles;
+            }
+
+            @Override
+            public Set<RoleModel> getClientRoleMappings(ClientModel app) {
+                Set<RoleModel> roles = super.getClientRoleMappings(app);
+
+                RoleModel role = getRole();
+                if (role != null && role.getContainer().equals(app)) {
+                    roles.add(role);
+                }
+
+                return roles;
+            }
+
+            @Override
+            public boolean hasRole(RoleModel role) {
+                return super.hasRole(role) || role.equals(getRole());
+            }
+
+            @Override
+            public Set<RoleModel> getRoleMappings() {
+                Set<RoleModel> roles = super.getRoleMappings();
+
+                RoleModel role = getRole();
+                if (role != null) {
+                    roles.add(role);
+                }
+
+                return roles;
+            }
+
+            @Override
+            public void deleteRoleMapping(RoleModel role) {
+                if (role.equals(getRole())) {
+                    throw new ModelException("Not possible to delete role. It's hardcoded by LDAP mapper");
+                } else {
+                    super.deleteRoleMapping(role);
+                }
+            }
+        };
+    }
+
+    @Override
+    public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) {
+
+    }
+
+    @Override
+    public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) {
+
+    }
+
+    private RoleModel getRole() {
+        String roleName = mapperModel.getConfig().get(HardcodedLDAPRoleMapper.ROLE);
+        RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
+        if (role == null) {
+            logger.warnf("Hardcoded role '%s' configured in mapper '%s' is not available anymore");
+        }
+        return role;
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapperFactory.java
new file mode 100644
index 0000000..508a333
--- /dev/null
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/HardcodedLDAPRoleMapperFactory.java
@@ -0,0 +1,78 @@
+package org.keycloak.federation.ldap.mappers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.keycloak.federation.ldap.LDAPFederationProvider;
+import org.keycloak.mappers.MapperConfigValidationException;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserFederationMapperModel;
+import org.keycloak.models.UserFederationProviderModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HardcodedLDAPRoleMapperFactory extends AbstractLDAPFederationMapperFactory {
+
+    public static final String PROVIDER_ID = "hardcoded-ldap-role-mapper";
+    protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+    static {
+        ProviderConfigProperty roleAttr = createConfigProperty(HardcodedLDAPRoleMapper.ROLE, "Role",
+                "Role to grant to user.  Click 'Select Role' button to browse roles, or just type it in the textbox.  To reference an application role the syntax is appname.approle, i.e. myapp.myrole",
+                ProviderConfigProperty.ROLE_TYPE, null);
+        configProperties.add(roleAttr);
+    }
+
+    @Override
+    public String getHelpText() {
+        return "When user is imported from LDAP, he will be automatically added into this configured role.";
+    }
+
+    @Override
+    public String getDisplayCategory() {
+        return ROLE_MAPPER_CATEGORY;
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Hardcoded Role";
+    }
+
+    @Override
+    public List<ProviderConfigProperty> getConfigProperties() {
+        return configProperties;
+    }
+
+    @Override
+    public Map<String, String> getDefaultConfig(UserFederationProviderModel providerModel) {
+        return new HashMap<>();
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+
+    @Override
+    public void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
+        String roleName = mapperModel.getConfig().get(HardcodedLDAPRoleMapper.ROLE);
+        if (roleName == null) {
+            throw new MapperConfigValidationException("Role can't be null");
+        }
+        RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
+        if (role == null) {
+            throw new MapperConfigValidationException("There is no role corresponding to configured value");
+        }
+    }
+
+    @Override
+    protected AbstractLDAPFederationMapper createMapper(UserFederationMapperModel mapperModel, LDAPFederationProvider federationProvider, RealmModel realm) {
+        return new HardcodedLDAPRoleMapper(mapperModel, federationProvider, realm);
+    }
+}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java
index 464cc0d..fa43ac9 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapperFactory.java
@@ -168,7 +168,7 @@ public class GroupLDAPFederationMapperFactory extends AbstractLDAPFederationMapp
     }
 
     @Override
-    public void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
+    public void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
         checkMandatoryConfigAttribute(GroupMapperConfig.GROUPS_DN, "LDAP Groups DN", mapperModel);
         checkMandatoryConfigAttribute(GroupMapperConfig.MODE, "Mode", mapperModel);
 
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapperFactory.java
index a4ba60f..fe0b1e1 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapperFactory.java
@@ -161,7 +161,7 @@ public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMappe
     }
 
     @Override
-    public void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
+    public void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
         checkMandatoryConfigAttribute(RoleMapperConfig.ROLES_DN, "LDAP Roles DN", mapperModel);
         checkMandatoryConfigAttribute(RoleMapperConfig.MODE, "Mode", mapperModel);
 
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapperFactory.java
index 9b061a6..5d92900 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapperFactory.java
@@ -87,7 +87,7 @@ public class UserAttributeLDAPFederationMapperFactory extends AbstractLDAPFedera
     }
 
     @Override
-    public void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
+    public void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
         checkMandatoryConfigAttribute(UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, "User Model Attribute", mapperModel);
         checkMandatoryConfigAttribute(UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, "LDAP Attribute", mapperModel);
     }
diff --git a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.mappers.UserFederationMapperFactory b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.mappers.UserFederationMapperFactory
index 9e4a658..ac130a5 100644
--- a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.mappers.UserFederationMapperFactory
+++ b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.mappers.UserFederationMapperFactory
@@ -1,4 +1,5 @@
 org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory
 org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory
+org.keycloak.federation.ldap.mappers.HardcodedLDAPRoleMapperFactory
 org.keycloak.federation.ldap.mappers.membership.role.RoleLDAPFederationMapperFactory
 org.keycloak.federation.ldap.mappers.membership.group.GroupLDAPFederationMapperFactory
\ No newline at end of file
diff --git a/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperFactory.java b/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperFactory.java
index f009c3e..eebc3d7 100644
--- a/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperFactory.java
+++ b/model/api/src/main/java/org/keycloak/mappers/UserFederationMapperFactory.java
@@ -2,6 +2,7 @@ package org.keycloak.mappers;
 
 import java.util.Map;
 
+import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserFederationMapperModel;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.provider.ConfiguredProvider;
@@ -37,7 +38,7 @@ public interface UserFederationMapperFactory extends ProviderFactory<UserFederat
      * @param mapperModel
      * @throws MapperConfigValidationException if configuration provided in mapperModel is not valid
      */
-    void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException;
+    void validateConfig(RealmModel realm, UserFederationMapperModel mapperModel) throws MapperConfigValidationException;
 
     /**
      * Used to detect what are default values for ProviderConfigProperties specified during mapper creation
diff --git a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
index f08eee4..6a77ac6 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -540,4 +540,34 @@ public final class KeycloakModelUtils {
         return result;
     }
 
+    // Used in various role mappers
+    public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
+        String[] parsedRole = parseRole(roleName);
+        RoleModel role = null;
+        if (parsedRole[0] == null) {
+            role = realm.getRole(parsedRole[1]);
+        } else {
+            ClientModel client = realm.getClientByClientId(parsedRole[0]);
+            if (client != null) {
+                role = client.getRole(parsedRole[1]);
+            }
+        }
+        return role;
+    }
+
+    // Used for hardcoded role mappers
+    public static String[] parseRole(String role) {
+        int scopeIndex = role.lastIndexOf('.');
+        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;
+
+        }
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
index c49eebb..a839e31 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
@@ -4,6 +4,7 @@ import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
@@ -67,7 +68,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
     public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
                                             UserSessionModel userSession, ClientSessionModel clientSession) {
         String role = mappingModel.getConfig().get(ROLE_CONFIG);
-        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
+        String[] scopedRole = KeycloakModelUtils.parseRole(role);
         String appName = scopedRole[0];
         String roleName = scopedRole[1];
         if (appName != null) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index 3ce1e19..5f0178c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
@@ -5,6 +5,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
@@ -78,8 +79,8 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
         String role = mappingModel.getConfig().get(ROLE_CONFIG);
         String newName = mappingModel.getConfig().get(NEW_ROLE_NAME);
 
-        String[] scopedRole = ProtocolMapperUtils.parseRole(role);
-        String[] newScopedRole = ProtocolMapperUtils.parseRole(newName);
+        String[] scopedRole = KeycloakModelUtils.parseRole(role);
+        String[] newScopedRole = KeycloakModelUtils.parseRole(newName);
         String appName = scopedRole[0];
         String roleName = scopedRole[1];
         if (appName != null) {
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
index 2b86773..9022c26 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapperUtils.java
@@ -47,20 +47,6 @@ public class ProtocolMapperUtils {
         return null;
     }
 
-    public static String[] parseRole(String role) {
-        int scopeIndex = role.lastIndexOf('.');
-        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;
-
-        }
-    }
-
     /**
      * Find the builtin locale mapper.
      *
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
index 1046276..2940247 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
@@ -353,7 +353,7 @@ public class UserFederationProviderResource {
     private void validateModel(UserFederationMapperModel model) {
         try {
             UserFederationMapperFactory mapperFactory = (UserFederationMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationMapper.class, model.getFederationMapperType());
-            mapperFactory.validateConfig(model);
+            mapperFactory.validateConfig(realm, model);
         } catch (MapperConfigValidationException ex) {
             throw new ErrorResponseException("Validation error", ex.getMessage(), Response.Status.BAD_REQUEST);
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
index 5702a45..1d41595 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/ldap/base/FederationProvidersIntegrationTest.java
@@ -15,11 +15,15 @@ import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
 import org.keycloak.federation.ldap.idm.model.LDAPObject;
 import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
 import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
+import org.keycloak.federation.ldap.mappers.HardcodedLDAPRoleMapper;
+import org.keycloak.federation.ldap.mappers.HardcodedLDAPRoleMapperFactory;
 import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.LDAPConstants;
+import org.keycloak.models.ModelException;
 import org.keycloak.models.ModelReadOnlyException;
 import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserCredentialValueModel;
 import org.keycloak.models.UserFederationMapperModel;
@@ -525,6 +529,50 @@ public class FederationProvidersIntegrationTest {
     }
 
     @Test
+    public void testHardcodedRoleMapper() {
+        KeycloakSession session = keycloakRule.startSession();
+        UserFederationMapperModel firstNameMapper = null;
+
+        try {
+            RealmModel appRealm = new RealmManager(session).getRealmByName("test");
+            RoleModel hardcodedRole = appRealm.addRole("hardcoded-role");
+
+            // assert that user "johnkeycloak" doesn't have hardcoded role
+            UserModel john = session.users().getUserByUsername("johnkeycloak", appRealm);
+            Assert.assertFalse(john.hasRole(hardcodedRole));
+
+            UserFederationMapperModel hardcodedMapperModel = KeycloakModelUtils.createUserFederationMapperModel("hardcoded role", ldapModel.getId(), HardcodedLDAPRoleMapperFactory.PROVIDER_ID,
+                    HardcodedLDAPRoleMapper.ROLE, "hardcoded-role");
+            appRealm.addUserFederationMapper(hardcodedMapperModel);
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+
+        session = keycloakRule.startSession();
+        try {
+            RealmModel appRealm = new RealmManager(session).getRealmByName("test");
+            RoleModel hardcodedRole = appRealm.getRole("hardcoded-role");
+
+            // Assert user is successfully imported in Keycloak DB now with correct firstName and lastName
+            UserModel john = session.users().getUserByUsername("johnkeycloak", appRealm);
+            Assert.assertTrue(john.hasRole(hardcodedRole));
+
+            // Can't remove user from hardcoded role
+            try {
+                john.deleteRoleMapping(hardcodedRole);
+                Assert.fail("Didn't expected to remove role mapping");
+            } catch (ModelException expected) {
+            }
+
+            // Revert mappers
+            UserFederationMapperModel hardcodedMapperModel = appRealm.getUserFederationMapperByName(ldapModel.getId(), "hardcoded role");
+            appRealm.removeUserFederationMapper(hardcodedMapperModel);
+        } finally {
+            keycloakRule.stopSession(session, true);
+        }
+    }
+
+    @Test
     public void testImportExistingUserFromLDAP() throws Exception {
         // Add LDAP user with same email like existing model user
         keycloakRule.update(new KeycloakRule.KeycloakSetup() {