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 new file mode 100755 index 0000000000..31684a097b --- /dev/null +++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedRoleMapper.java @@ -0,0 +1,110 @@ +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.provider.ProviderConfigProperty; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class HardcodedRoleMapper extends AbstractIdentityProviderMapper { + public static final String ROLE = "role"; + protected static final List configProperties = new ArrayList(); + + static { + ProviderConfigProperty property; + property = new ProviderConfigProperty(); + property.setName(ROLE); + property.setLabel("Role"); + property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.STRING_TYPE); + configProperties.add(property); + } + + + + 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; + + } + } + + 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 getConfigProperties() { + return configProperties; + } + + @Override + public String getDisplayCategory() { + return "Role Importer"; + } + + @Override + public String getDisplayType() { + return "Hardcoded Role"; + } + + public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER}; + + + public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper"; + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public String[] getCompatibleProviders() { + return COMPATIBLE_PROVIDERS; + } + + @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); + if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName); + user.grantRole(role); + } + + @Override + public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + + } + + @Override + public String getHelpText() { + return "When user is imported from provider, hardcode a role mapping for it."; + } +} diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java index 990c6de09b..40174999da 100755 --- a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java +++ b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderMapper.java @@ -13,6 +13,8 @@ import org.keycloak.provider.ProviderFactory; * @version $Revision: 1 $ */ public interface IdentityProviderMapper extends Provider, ProviderFactory,ConfiguredProvider { + public static final String ANY_PROVIDER = "*"; + String[] getCompatibleProviders(); String getDisplayCategory(); String getDisplayType(); diff --git a/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper new file mode 100755 index 0000000000..a3bf053820 --- /dev/null +++ b/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper @@ -0,0 +1 @@ +org.keycloak.broker.provider.HardcodedRoleMapper \ No newline at end of file diff --git a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/RoleMapper.java b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java similarity index 68% rename from broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/RoleMapper.java rename to broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java index 7f47590159..564ac9c743 100755 --- a/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/RoleMapper.java +++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ClaimToRoleMapper.java @@ -3,8 +3,8 @@ package org.keycloak.broker.oidc.mappers; import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory; import org.keycloak.broker.oidc.OIDCIdentityProviderFactory; import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.broker.provider.HardcodedRoleMapper; 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; @@ -19,14 +19,12 @@ import java.util.List; * @author Bill Burke * @version $Revision: 1 $ */ -public class RoleMapper extends AbstractClaimMapper { +public class ClaimToRoleMapper extends AbstractClaimMapper { public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID}; private static final List configProperties = new ArrayList(); - public static final String ROLE = "role"; - static { ProviderConfigProperty property; ProviderConfigProperty property1; @@ -43,29 +41,15 @@ public class RoleMapper extends AbstractClaimMapper { property1.setType(ProviderConfigProperty.STRING_TYPE); configProperties.add(property1); property = new ProviderConfigProperty(); - property.setName(ROLE); + property.setName(HardcodedRoleMapper.ROLE); property.setLabel("Role"); - property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setHelpText("Role to grant to user if claim is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); property.setType(ProviderConfigProperty.STRING_TYPE); configProperties.add(property); } public static final String PROVIDER_ID = "oidc-role-idp-mapper"; - 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; - - } - } - @Override public List getConfigProperties() { @@ -89,36 +73,24 @@ public class RoleMapper extends AbstractClaimMapper { @Override public String getDisplayType() { - return "Role Importer"; + return "Claim to Role"; } @Override public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { - String roleName = mapperModel.getConfig().get(ROLE); + String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE); if (hasClaimValue(mapperModel, context)) { - RoleModel role = getRoleFromString(realm, roleName); + RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName); if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName); user.grantRole(role); } } - protected 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 void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { - String roleName = mapperModel.getConfig().get(ROLE); + String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE); if (!hasClaimValue(mapperModel, context)) { - RoleModel role = getRoleFromString(realm, roleName); + RoleModel role = HardcodedRoleMapper.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 new file mode 100755 index 0000000000..f5bf539d47 --- /dev/null +++ b/broker/oidc/src/main/java/org/keycloak/broker/oidc/mappers/ExternalKeycloakRoleToRoleMapper.java @@ -0,0 +1,118 @@ +package org.keycloak.broker.oidc.mappers; + +import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider; +import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory; +import org.keycloak.broker.oidc.OIDCIdentityProviderFactory; +import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.broker.provider.HardcodedRoleMapper; +import org.keycloak.broker.provider.IdentityBrokerException; +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.provider.ProviderConfigProperty; +import org.keycloak.representations.JsonWebToken; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper { + + public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID}; + + private static final List configProperties = new ArrayList(); + private static final String EXTERNAL_ROLE = "external.role"; + + static { + ProviderConfigProperty property; + ProviderConfigProperty property1; + property1 = new ProviderConfigProperty(); + property1.setName(EXTERNAL_ROLE); + property1.setLabel("External role"); + property1.setHelpText("External role to check for. To reference an application role the syntax is appname.approle, i.e. myapp.myrole."); + property1.setType(ProviderConfigProperty.STRING_TYPE); + configProperties.add(property1); + property = new ProviderConfigProperty(); + property.setName(HardcodedRoleMapper.ROLE); + property.setLabel("Role"); + property.setHelpText("Role to grant to user if external role is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); + property.setType(ProviderConfigProperty.STRING_TYPE); + configProperties.add(property); + } + + public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper"; + + + @Override + public List getConfigProperties() { + return configProperties; + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public String[] getCompatibleProviders() { + return COMPATIBLE_PROVIDERS; + } + + @Override + public String getDisplayCategory() { + return "Role Importer"; + } + + @Override + public String getDisplayType() { + return "External Role to Role"; + } + + @Override + public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + RoleModel role = hasRole(realm, mapperModel, context); + if (role != null) { + user.grantRole(role); + } + } + + private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + 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 externalRoleName = parseRole[1]; + String claimName = null; + if (parseRole[0] == null) { + claimName = "realm_access.roles"; + } else { + claimName = "resource_access." + parseRole[0] + ".roles"; + } + Object claim = getClaimValue(token, claimName); + if (valueEquals(externalRoleName, claim)) { + RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName); + if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName); + return role; + } + return null; + } + + @Override + public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + RoleModel role = hasRole(realm, mapperModel, context); + if (role == null) { + user.deleteRoleMapping(role); + } + } + + @Override + public String getHelpText() { + return "Looks for an external role in a keycloak access token. If external role exists, grant the user the specified realm or application role."; + } + +} diff --git a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper index c2245b6444..de86af2eec 100755 --- a/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper +++ b/broker/oidc/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper @@ -1,2 +1,3 @@ -org.keycloak.broker.oidc.mappers.RoleMapper +org.keycloak.broker.oidc.mappers.ClaimToRoleMapper +org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper org.keycloak.broker.oidc.mappers.UserAttributeMapper \ No newline at end of file diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java similarity index 79% rename from broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java rename to broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java index 7181dfee3c..9c37dd8c98 100755 --- a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/AttributeToRoleMapper.java @@ -2,6 +2,7 @@ package org.keycloak.broker.saml.mappers; import org.keycloak.broker.provider.AbstractIdentityProviderMapper; import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.broker.provider.HardcodedRoleMapper; import org.keycloak.broker.provider.IdentityBrokerException; import org.keycloak.broker.saml.SAMLEndpoint; import org.keycloak.broker.saml.SAMLIdentityProviderFactory; @@ -25,13 +26,12 @@ import java.util.Map; * @author Bill Burke * @version $Revision: 1 $ */ -public class RoleMapper extends AbstractIdentityProviderMapper { +public class AttributeToRoleMapper extends AbstractIdentityProviderMapper { public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID}; private static final List configProperties = new ArrayList(); - public static final String ROLE = "role"; public static final String ATTRIBUTE_NAME = "attribute.name"; public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name"; public static final String ATTRIBUTE_VALUE = "attribute.value"; @@ -57,7 +57,7 @@ public class RoleMapper extends AbstractIdentityProviderMapper { property.setType(ProviderConfigProperty.STRING_TYPE); configProperties.add(property); property = new ProviderConfigProperty(); - property.setName(ROLE); + property.setName(HardcodedRoleMapper.ROLE); property.setLabel("Role"); property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole"); property.setType(ProviderConfigProperty.STRING_TYPE); @@ -66,20 +66,6 @@ public class RoleMapper extends AbstractIdentityProviderMapper { public static final String PROVIDER_ID = "saml-role-idp-mapper"; - 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; - - } - } - @Override public List getConfigProperties() { return configProperties; @@ -102,31 +88,19 @@ public class RoleMapper extends AbstractIdentityProviderMapper { @Override public String getDisplayType() { - return "Role Mapper"; + return "SAML Attribute to Role"; } @Override public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { - String roleName = mapperModel.getConfig().get(ROLE); + String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE); if (isAttributePresent(mapperModel, context)) { - RoleModel role = getRoleFromString(realm, roleName); + RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName); if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName); user.grantRole(role); } } - protected 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; - } - protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String name = mapperModel.getConfig().get(ATTRIBUTE_NAME); if (name != null && name.trim().equals("")) name = null; @@ -149,9 +123,9 @@ public class RoleMapper extends AbstractIdentityProviderMapper { @Override public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { - String roleName = mapperModel.getConfig().get(ROLE); + String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE); if (!isAttributePresent(mapperModel, context)) { - RoleModel role = getRoleFromString(realm, roleName); + RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName); if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName); user.deleteRoleMapping(role); } diff --git a/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper index 5051d1d517..9de7273b79 100755 --- a/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper +++ b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper @@ -1,2 +1,2 @@ -org.keycloak.broker.saml.mappers.RoleMapper +org.keycloak.broker.saml.mappers.AttributeToRoleMapper org.keycloak.broker.saml.mappers.UserAttributeMapper \ No newline at end of file diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java index e51c209769..c10ef1e2b7 100755 --- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java +++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java @@ -283,9 +283,10 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal } catch (Exception e) { return redirectToLoginPage(e, clientCode); } + } else { + updateFederatedIdentity(context, federatedUser); } - updateFederatedIdentity(context, federatedUser); UserSessionModel userSession = this.session.sessions() .createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, context.getBrokerSessionId(), context.getBrokerUserId()); @@ -335,26 +336,26 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build(); } - private void updateFederatedIdentity(BrokeredIdentityContext updatedIdentity, UserModel federatedUser) { - FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, updatedIdentity.getIdpConfig().getAlias(), this.realmModel); + private void updateFederatedIdentity(BrokeredIdentityContext context, UserModel federatedUser) { + FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel); // Skip DB write if tokens are null or equal - if (!ObjectUtil.isEqualOrNull(updatedIdentity.getToken(), federatedIdentityModel.getToken())) { - federatedIdentityModel.setToken(updatedIdentity.getToken()); + if (context.getIdpConfig().isStoreToken() && !ObjectUtil.isEqualOrNull(context.getToken(), federatedIdentityModel.getToken())) { + federatedIdentityModel.setToken(context.getToken()); this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel); if (isDebugEnabled()) { - LOGGER.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, updatedIdentity.getIdpConfig().getAlias()); + LOGGER.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias()); } } - updatedIdentity.getIdp().updateBrokeredUser(session, realmModel, federatedUser, updatedIdentity); - Set mappers = realmModel.getIdentityProviderMappersByAlias(updatedIdentity.getIdpConfig().getAlias()); + context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context); + Set mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias()); if (mappers != null) { KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (IdentityProviderMapperModel mapper : mappers) { IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.updateBrokeredUser(session, realmModel, federatedUser, mapper, updatedIdentity); + target.updateBrokeredUser(session, realmModel, federatedUser, mapper, context); } } @@ -484,14 +485,14 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal throw new IdentityBrokerException("Configuration for identity provider [" + providerId + "] not found."); } - private UserModel createUser(BrokeredIdentityContext updatedIdentity) { - FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(updatedIdentity.getIdpConfig().getAlias(), updatedIdentity.getId(), - updatedIdentity.getUsername(), updatedIdentity.getToken()); + private UserModel createUser(BrokeredIdentityContext context) { + FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(), + context.getUsername(), context.getToken()); // Check if no user already exists with this username or email UserModel existingUser = null; - if (updatedIdentity.getEmail() != null) { - existingUser = this.session.users().getUserByEmail(updatedIdentity.getEmail(), this.realmModel); + if (context.getEmail() != null) { + existingUser = this.session.users().getUserByEmail(context.getEmail(), this.realmModel); } if (existingUser != null) { @@ -499,13 +500,13 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal throw new IdentityBrokerException(Messages.FEDERATED_IDENTITY_EMAIL_EXISTS); } - String username = updatedIdentity.getUsername(); - if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(updatedIdentity.getEmail())) { - username = updatedIdentity.getEmail(); + String username = context.getUsername(); + if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(context.getEmail())) { + username = context.getEmail(); } else if (username == null) { - username = updatedIdentity.getIdpConfig().getAlias() + "." + updatedIdentity.getId(); + username = context.getIdpConfig().getAlias() + "." + context.getId(); } else { - username = updatedIdentity.getIdpConfig().getAlias() + "." + updatedIdentity.getUsername(); + username = context.getIdpConfig().getAlias() + "." + context.getUsername(); } if (username != null) { username = username.trim(); @@ -529,33 +530,36 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal } federatedUser.setEnabled(true); - federatedUser.setEmail(updatedIdentity.getEmail()); - federatedUser.setFirstName(updatedIdentity.getFirstName()); - federatedUser.setLastName(updatedIdentity.getLastName()); + federatedUser.setEmail(context.getEmail()); + federatedUser.setFirstName(context.getFirstName()); + federatedUser.setLastName(context.getLastName()); - if (updatedIdentity.getIdpConfig().isAddReadTokenRoleOnCreate()) { + if (context.getIdpConfig().isAddReadTokenRoleOnCreate()) { RoleModel readTokenRole = realmModel.getClientByClientId(Constants.BROKER_SERVICE_CLIENT_ID).getRole(READ_TOKEN_ROLE); federatedUser.grantRole(readTokenRole); } + if (context.getIdpConfig().isStoreToken()) { + federatedIdentityModel.setToken(context.getToken()); + } this.session.users().addFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel); - updatedIdentity.getIdp().importNewUser(session, realmModel, federatedUser, updatedIdentity); - Set mappers = realmModel.getIdentityProviderMappersByAlias(updatedIdentity.getIdpConfig().getAlias()); + context.getIdp().importNewUser(session, realmModel, federatedUser, context); + Set mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias()); if (mappers != null) { KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); for (IdentityProviderMapperModel mapper : mappers) { IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper()); - target.importNewUser(session, realmModel, federatedUser, mapper, updatedIdentity); + target.importNewUser(session, realmModel, federatedUser, mapper, context); } } this.event.clone().user(federatedUser).event(EventType.REGISTER) .detail(Details.IDENTITY_PROVIDER, federatedIdentityModel.getIdentityProvider()) - .detail(Details.IDENTITY_PROVIDER_USERNAME, updatedIdentity.getUsername()) + .detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername()) .removeDetail("auth_method") .success(); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java index 114aa0690e..539c41094e 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java @@ -181,7 +181,7 @@ public class IdentityProviderResource { for (ProviderFactory factory : factories) { IdentityProviderMapper mapper = (IdentityProviderMapper)factory; for (String type : mapper.getCompatibleProviders()) { - if (type.equals(identityProviderModel.getProviderId())) { + if (IdentityProviderMapper.ANY_PROVIDER.equals(type) || type.equals(identityProviderModel.getProviderId())) { IdentityProviderMapperTypeRepresentation rep = new IdentityProviderMapperTypeRepresentation(); rep.setId(mapper.getId()); rep.setCategory(mapper.getDisplayCategory()); @@ -198,7 +198,7 @@ public class IdentityProviderResource { rep.getProperties().add(propRep); } types.put(rep.getId(), rep); - + break; } } } diff --git a/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java b/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java index 7a38655c1d..3f20d1634b 100755 --- a/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java +++ b/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java @@ -22,6 +22,7 @@ package org.keycloak.testsuite; import org.apache.catalina.startup.Tomcat; +import org.apache.tomcat.util.http.mapper.Mapper; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule;