From 69a146db7e91afdbc6935300b6975fa52a376eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Muzik=C3=A1=C5=99?= Date: Fri, 20 Aug 2021 19:34:55 +0200 Subject: [PATCH] KEYCLOAK-18128 Keycloak cannot fetch group claims from openshift --- .../openshift/OpenshiftV4AttributeMapper.java | 38 +++++++++++++++++++ ...oak.broker.provider.IdentityProviderMapper | 1 + .../testsuite/broker/SocialLoginTest.java | 36 +++++++++++------- 3 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 services/src/main/java/org/keycloak/social/openshift/OpenshiftV4AttributeMapper.java diff --git a/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4AttributeMapper.java b/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4AttributeMapper.java new file mode 100644 index 0000000000..d5d7ca286e --- /dev/null +++ b/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4AttributeMapper.java @@ -0,0 +1,38 @@ +/* + * Copyright 2021 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.social.openshift; + +import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper; + +/** + * @author Vaclav Muzikar + */ +public class OpenshiftV4AttributeMapper extends AbstractJsonUserAttributeMapper { + public static final String ID = "openshift-v4-user-attribute-mapper"; + private static final String[] cp = new String[] { OpenshiftV4IdentityProviderFactory.PROVIDER_ID }; + + @Override + public String[] getCompatibleProviders() { + return cp; + } + + @Override + public String getId() { + return ID; + } +} 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 35f5ce7af5..d9fc841828 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 @@ -35,3 +35,4 @@ org.keycloak.social.linkedin.LinkedInUserAttributeMapper org.keycloak.social.stackoverflow.StackoverflowUserAttributeMapper org.keycloak.social.microsoft.MicrosoftUserAttributeMapper org.keycloak.social.instagram.InstagramUserAttributeMapper +org.keycloak.social.openshift.OpenshiftV4AttributeMapper diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java index eda979bdfa..300726fbb9 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java @@ -106,7 +106,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { public static final String REALM = "social"; public static final String EXCHANGE_CLIENT = "exchange-client"; - private static Properties config = new Properties(); + private static final Properties config = new Properties(); @Page private LoginPage loginPage; @@ -133,8 +133,8 @@ public class SocialLoginTest extends AbstractKeycloakTest { BITBUCKET("bitbucket", BitbucketLoginPage.class), INSTAGRAM("instagram", InstagramLoginPage.class); - private String id; - private Class pageObjectClazz; + private final String id; + private final Class pageObjectClazz; private String configId = null; Provider(String id, Class pageObjectClazz) { @@ -255,6 +255,17 @@ public class SocialLoginTest extends AbstractKeycloakTest { testTokenExchange(); } + @Test + @UncaughtServerErrorExpected + public void openshift4LoginWithGroupsMapper() { + setTestProvider(OPENSHIFT4); + addAttributeMapper("ocp-groups", "groups"); + performLogin(); + assertUpdateProfile(false, false, true); + assertAccount(); + assertAttribute("ocp-groups", getConfig("groups")); + } + @Test @UncaughtServerErrorExpected public void googleLogin() throws InterruptedException { @@ -322,10 +333,10 @@ public class SocialLoginTest extends AbstractKeycloakTest { @UncaughtServerErrorExpected public void facebookLoginWithEnhancedScope() throws InterruptedException { setTestProvider(FACEBOOK_INCLUDE_BIRTHDAY); - addBirthdayMapper(); + addAttributeMapper("birthday", "birthday"); performLogin(); assertAccount(); - assertBirthdayAttribute(); + assertAttribute("birthday", getConfig("profile.birthday")); testTokenExchange(); } @@ -429,18 +440,18 @@ public class SocialLoginTest extends AbstractKeycloakTest { return idp; } - private void addBirthdayMapper() { + private void addAttributeMapper(String name, String jsonField) { IdentityProviderResource identityProvider = adminClient.realm(REALM).identityProviders().get(currentTestProvider.id); IdentityProviderRepresentation identityProviderRepresentation = identityProvider.toRepresentation(); //Add birthday mapper IdentityProviderMapperRepresentation mapperRepresentation = new IdentityProviderMapperRepresentation(); - mapperRepresentation.setName(currentTestProvider.id + "-birthday-mapper"); + mapperRepresentation.setName(name); mapperRepresentation.setIdentityProviderAlias(identityProviderRepresentation.getAlias()); mapperRepresentation.setIdentityProviderMapper(currentTestProvider.id + "-user-attribute-mapper"); mapperRepresentation.setConfig(ImmutableMap.builder() .put(IdentityProviderMapperModel.SYNC_MODE, IdentityProviderMapperSyncMode.IMPORT.toString()) - .put(AbstractJsonUserAttributeMapper.CONF_JSON_FIELD, "birthday") - .put(AbstractJsonUserAttributeMapper.CONF_USER_ATTRIBUTE, currentTestProvider.id + "_birthday") + .put(AbstractJsonUserAttributeMapper.CONF_JSON_FIELD, jsonField) + .put(AbstractJsonUserAttributeMapper.CONF_USER_ATTRIBUTE, name) .build()); identityProvider.addMapper(mapperRepresentation).close(); } @@ -490,13 +501,12 @@ public class SocialLoginTest extends AbstractKeycloakTest { assertEquals(getConfig("profile.email"), accountPage.getEmail()); } - private void assertBirthdayAttribute() { + private void assertAttribute(String attrName, String expectedValue) { List users = adminClient.realm(REALM).users().search(null, null, null); assertEquals(1, users.size()); assertNotNull(users.get(0).getAttributes()); - final String birthdayAttributeKey = currentTestProvider.id + "_birthday"; - assertNotNull(users.get(0).getAttributes().get(birthdayAttributeKey)); - assertEquals(getConfig("profile.birthday"), users.get(0).getAttributes().get(birthdayAttributeKey).get(0)); + assertNotNull(users.get(0).getAttributes().get(attrName)); + assertEquals(expectedValue, users.get(0).getAttributes().get(attrName).get(0)); } private void assertUpdateProfile(boolean firstName, boolean lastName, boolean email) {