diff --git a/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4IdentityProvider.java b/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4IdentityProvider.java index fc45032421..c4dbabe43e 100644 --- a/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4IdentityProvider.java +++ b/services/src/main/java/org/keycloak/social/openshift/OpenshiftV4IdentityProvider.java @@ -3,7 +3,6 @@ package org.keycloak.social.openshift; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.HttpResponse; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider; @@ -16,7 +15,6 @@ import org.keycloak.connections.httpclient.HttpClientProvider; import org.keycloak.events.EventBuilder; import org.keycloak.models.KeycloakSession; -import javax.ws.rs.core.Response; import java.io.IOException; import java.io.InputStream; import java.util.Map; @@ -33,6 +31,7 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider< public static final String OPENSHIFT_OAUTH_METADATA_ENDPOINT = "/.well-known/oauth-authorization-server"; public static final String PROFILE_RESOURCE = "/apis/user.openshift.io/v1/users/~"; public static final String DEFAULT_SCOPE = "user:info"; + private static final String KUBEADM_NAME = "kube:admin"; public OpenshiftV4IdentityProvider(KeycloakSession session, OpenshiftV4IdentityProviderConfig config) { super(session, config); @@ -91,7 +90,11 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider< private BrokeredIdentityContext extractUserContext(JsonNode profile) { JsonNode metadata = profile.get("metadata"); logger.debugv("extractUserContext: metadata = {0}", metadata); - final BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(metadata, "uid")); + final BrokeredIdentityContext user = new BrokeredIdentityContext( + getJsonProperty(metadata, "uid") != null + ? getJsonProperty(metadata, "uid") + : tryGetKubeAdmin(metadata) + ); user.setUsername(getJsonProperty(metadata, "name")); user.setName(getJsonProperty(profile, "fullName")); user.setIdpConfig(getConfig()); @@ -99,6 +102,14 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider< return user; } + private String tryGetKubeAdmin(JsonNode metadata) { + String nameProperty = getJsonProperty(metadata, "name"); + if(!KUBEADM_NAME.equals(nameProperty)){ + return null; + } + return nameProperty; + } + private JsonNode fetchProfile(String accessToken) throws IOException { return SimpleHttp.doGet(getConfig().getUserInfoUrl(), this.session) .header("Authorization", "Bearer " + accessToken) diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/social/OpenShiftLoginPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/social/OpenShiftLoginPage.java index f684fce31c..055bf8e2f3 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/social/OpenShiftLoginPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/social/OpenShiftLoginPage.java @@ -17,10 +17,14 @@ package org.keycloak.testsuite.pages.social; +import org.openqa.selenium.By; import org.openqa.selenium.Keys; +import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; +import static org.keycloak.testsuite.util.UIUtils.clickLink; + /** * @author Vaclav Muzikar */ @@ -31,10 +35,33 @@ public class OpenShiftLoginPage extends AbstractSocialLoginPage { @FindBy(name = "password") private WebElement passwordInput; + private String userLoginLinkTitle; + + private WebElement userLoginLink; + @Override public void login(String user, String password) { + if(userLoginLinkTitle != null) { + setUserLoginLink(this.userLoginLinkTitle); + if(this.userLoginLink != null) { + clickLink(this.userLoginLink); + } + } + usernameInput.sendKeys(user); passwordInput.sendKeys(password); passwordInput.sendKeys(Keys.RETURN); } + + public void setUserLoginLinkTitle(String title) { + this.userLoginLinkTitle = title; + } + + private void setUserLoginLink(String linkAttrTitle) { + try { + this.userLoginLink = driver.findElement(By.xpath("//a[contains(@title,'"+linkAttrTitle+"')]")); + } catch (NoSuchElementException ex) { + log.error("No link with title: '" + linkAttrTitle + "' found on page. If you use the OPENSHIFT4_KUBE_ADMIN provider, set property loginBtnTitle in properties file to an existing title on the page to fix this error."); + } + } } 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 f6683b18e1..071f3fdfde 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 @@ -88,6 +88,7 @@ import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.LINKEDIN; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.MICROSOFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4; +import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4_KUBE_ADMIN; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.PAYPAL; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.STACKOVERFLOW; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.TWITTER; @@ -129,6 +130,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { STACKOVERFLOW("stackoverflow", StackOverflowLoginPage.class), OPENSHIFT("openshift-v3", OpenShiftLoginPage.class), OPENSHIFT4("openshift-v4", OpenShiftLoginPage.class), + OPENSHIFT4_KUBE_ADMIN("openshift-v4", "openshift-v4-admin", OpenShiftLoginPage.class), GITLAB("gitlab", GitLabLoginPage.class), BITBUCKET("bitbucket", BitbucketLoginPage.class), INSTAGRAM("instagram", InstagramLoginPage.class); @@ -195,6 +197,10 @@ public class SocialLoginTest extends AbstractKeycloakTest { log.infof("added '%s' identity provider", provider.id()); currentTestProvider = provider; currentSocialLoginPage = Graphene.createPageFragment(currentTestProvider.pageObjectClazz(), driver.findElement(By.tagName("html"))); + + if(provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) { + ((OpenShiftLoginPage) currentSocialLoginPage).setUserLoginLinkTitle(getConfig(currentTestProvider, "loginBtnTitle")); + } } @Override @@ -255,6 +261,14 @@ public class SocialLoginTest extends AbstractKeycloakTest { testTokenExchange(); } + @Test + public void openshift4KubeAdminLogin() { + setTestProvider(OPENSHIFT4_KUBE_ADMIN); + performLogin(); + assertUpdateProfile(true, true, true); + assertAccount(); + } + @Test @UncaughtServerErrorExpected public void openshift4LoginWithGroupsMapper() { @@ -426,7 +440,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { if (provider == STACKOVERFLOW) { idp.getConfig().put("key", getConfig(provider, "clientKey")); } - if (provider == OPENSHIFT || provider == OPENSHIFT4) { + if (provider == OPENSHIFT || provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) { idp.getConfig().put("baseUrl", getConfig(provider, "baseUrl")); } if (provider == PAYPAL) {