diff --git a/services/src/main/java/org/keycloak/broker/provider/HardcodedGroupMapper.java b/services/src/main/java/org/keycloak/broker/provider/HardcodedGroupMapper.java new file mode 100755 index 0000000000..82dbdfa3ba --- /dev/null +++ b/services/src/main/java/org/keycloak/broker/provider/HardcodedGroupMapper.java @@ -0,0 +1,98 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.broker.provider; + +import org.jboss.logging.Logger; +import org.keycloak.broker.oidc.mappers.AbstractClaimToGroupMapper; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderSyncMode; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Daniele Martinoli + * @version $Revision: 1 $ + */ +public class HardcodedGroupMapper extends AbstractClaimToGroupMapper { + protected static final List configProperties = new ArrayList<>(); + + private static final Logger LOG = Logger.getLogger(HardcodedGroupMapper.class); + + private static final Set IDENTITY_PROVIDER_SYNC_MODES = + new HashSet<>(Arrays.asList(IdentityProviderSyncMode.values())); + + static { + ProviderConfigProperty property; + property = new ProviderConfigProperty(); + property.setName(ConfigConstants.GROUP); + property.setLabel("Group"); + property.setHelpText("Group to assign the user."); + property.setType(ProviderConfigProperty.GROUP_TYPE); + configProperties.add(property); + } + + @Override + public List getConfigProperties() { + return configProperties; + } + + @Override + public String getDisplayCategory() { + return "Group Importer"; + } + + @Override + public String getDisplayType() { + return "Hardcoded Group"; + } + + public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER}; + + + public static final String PROVIDER_ID = "oidc-hardcoded-group-idp-mapper"; + + @Override + public boolean supportsSyncMode(IdentityProviderSyncMode syncMode) { + return IDENTITY_PROVIDER_SYNC_MODES.contains(syncMode); + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public String[] getCompatibleProviders() { + return COMPATIBLE_PROVIDERS; + } + + @Override + public String getHelpText() { + return "Assign the user to the specified group."; + } + + @Override + protected boolean applies(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + return true; + } +} diff --git a/services/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/services/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper index 7602e33ef6..694d41455a 100755 --- a/services/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper +++ b/services/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper @@ -15,6 +15,7 @@ # limitations under the License. # +org.keycloak.broker.provider.HardcodedGroupMapper org.keycloak.broker.provider.HardcodedRoleMapper org.keycloak.broker.provider.HardcodedAttributeMapper org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcAdvancedClaimToGroupMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcAdvancedClaimToGroupMapperTest.java index 776a258f44..16b08dd0e7 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcAdvancedClaimToGroupMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcAdvancedClaimToGroupMapperTest.java @@ -26,6 +26,9 @@ import jakarta.ws.rs.core.Response; * Daniel Fesenmeyer */ public class OidcAdvancedClaimToGroupMapperTest extends AbstractGroupBrokerMapperTest { + protected boolean isHardcodedGroup() { + return false; + } @Override protected BrokerConfiguration getBrokerConfiguration() { @@ -74,7 +77,11 @@ public class OidcAdvancedClaimToGroupMapperTest extends AbstractGroupBrokerMappe logInAsUserInIDPForFirstTimeAndAssertSuccess(); UserRepresentation user = findUser(bc.consumerRealmName(), bc.getUserLogin(), bc.getUserEmail()); - assertThatUserHasNotBeenAssignedToGroup(user); + if (!isHardcodedGroup()) { + assertThatUserHasNotBeenAssignedToGroup(user); + } else { + assertThatUserHasBeenAssignedToGroup(user); + } } @Test @@ -113,7 +120,11 @@ public class OidcAdvancedClaimToGroupMapperTest extends AbstractGroupBrokerMappe logInAsUserInIDPForFirstTimeAndAssertSuccess(); UserRepresentation user = findUser(bc.consumerRealmName(), bc.getUserLogin(), bc.getUserEmail()); - assertThatUserHasNotBeenAssignedToGroup(user); + if (!isHardcodedGroup()) { + assertThatUserHasNotBeenAssignedToGroup(user); + } else { + assertThatUserHasBeenAssignedToGroup(user); + } } @Test @@ -121,7 +132,11 @@ public class OidcAdvancedClaimToGroupMapperTest extends AbstractGroupBrokerMappe newValueForAttribute2 = "value mismatch"; UserRepresentation user = createMapperAndLoginAsUserTwiceWithMapper(FORCE, false, MAPPER_TEST_GROUP_PATH); - assertThatUserHasNotBeenAssignedToGroup(user); + if (!isHardcodedGroup()) { + assertThatUserHasNotBeenAssignedToGroup(user); + } else { + assertThatUserHasBeenAssignedToGroup(user); + } } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcHardcodedGroupMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcHardcodedGroupMapperTest.java new file mode 100644 index 0000000000..dc8951faf7 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/OidcHardcodedGroupMapperTest.java @@ -0,0 +1,52 @@ +package org.keycloak.testsuite.broker; + +import org.keycloak.admin.client.CreatedResponseUtil; +import org.keycloak.admin.client.resource.IdentityProviderResource; +import org.keycloak.broker.provider.ConfigConstants; +import org.keycloak.broker.provider.HardcodedGroupMapper; +import org.keycloak.models.IdentityProviderMapperModel; +import org.keycloak.models.IdentityProviderMapperSyncMode; +import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; + +import com.google.common.collect.ImmutableMap; + +import jakarta.ws.rs.core.Response; + +/** + * @author DanieleMartinoli + * + * For simplicity, it overrides OidcAdvancedClaimToGroupMapperTest with an Hardcoded Group mapper to run + * all tests from the super class. + * + * Since this mapper does not cause leaving the group when the claims do not match, an isHardcodedGroup + * method is introduced to customize the behavior in the super class. + */ +public class OidcHardcodedGroupMapperTest extends OidcAdvancedClaimToGroupMapperTest { + @Override + protected boolean isHardcodedGroup() { + return true; + } + + @Override + protected BrokerConfiguration getBrokerConfiguration() { + return new KcOidcBrokerConfiguration(); + } + + @Override + protected String createMapperInIdp(IdentityProviderRepresentation idp, String claimsOrAttributeRepresentation, + boolean areClaimsOrAttributeValuesRegexes, IdentityProviderMapperSyncMode syncMode, String groupPath) { + IdentityProviderMapperRepresentation hardcodedGroupMapper = new IdentityProviderMapperRepresentation(); + hardcodedGroupMapper.setName("hardcoded-group-mapper"); + hardcodedGroupMapper.setIdentityProviderMapper(HardcodedGroupMapper.PROVIDER_ID); + hardcodedGroupMapper.setConfig(ImmutableMap. builder() + .put(IdentityProviderMapperModel.SYNC_MODE, syncMode.toString()) + .put(ConfigConstants.GROUP, groupPath) + .build()); + + IdentityProviderResource idpResource = realm.identityProviders().get(idp.getAlias()); + hardcodedGroupMapper.setIdentityProviderAlias(bc.getIDPAlias()); + Response response = idpResource.addMapper(hardcodedGroupMapper); + return CreatedResponseUtil.getCreatedId(response); + } +}