Adds Openshift Identity Provider as part of social brokers
This commit is contained in:
parent
b8767d13d5
commit
1a6bb2fedb
8 changed files with 155 additions and 0 deletions
|
@ -0,0 +1,20 @@
|
|||
package org.keycloak.social.openshift;
|
||||
|
||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
|
||||
public class OpenshifV3IdentityProviderConfig extends OAuth2IdentityProviderConfig {
|
||||
private static final String BASE_URL = "baseUrl";
|
||||
|
||||
public OpenshifV3IdentityProviderConfig(IdentityProviderModel identityProviderModel) {
|
||||
super(identityProviderModel);
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return getConfig().get(BASE_URL);
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
getConfig().put(BASE_URL, baseUrl);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package org.keycloak.social.openshift;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
||||
import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
|
||||
import org.keycloak.broker.oidc.util.JsonSimpleHttp;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.broker.social.SocialIdentityProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Identity provider for Openshift V3. Check <a href="https://docs.openshift.com/enterprise/3.0/architecture/additional_concepts/authentication.html">official documentation</a> for more details.
|
||||
*/
|
||||
public class OpenshiftV3IdentityProvider extends AbstractOAuth2IdentityProvider<OpenshifV3IdentityProviderConfig> implements SocialIdentityProvider<OpenshifV3IdentityProviderConfig> {
|
||||
|
||||
public static final String BASE_URL = "https://api.preview.openshift.com";
|
||||
private static final String AUTH_RESOURCE = "/oauth/authorize";
|
||||
private static final String TOKEN_RESOURCE = "/oauth/token";
|
||||
private static final String PROFILE_RESOURCE = "/oapi/v1/users/~";
|
||||
private static final String DEFAULT_SCOPE = "user:info";
|
||||
|
||||
public OpenshiftV3IdentityProvider(KeycloakSession session, OpenshifV3IdentityProviderConfig config) {
|
||||
super(session, config);
|
||||
final String baseUrl = Optional.ofNullable(config.getBaseUrl()).orElse(BASE_URL);
|
||||
config.setAuthorizationUrl(baseUrl + AUTH_RESOURCE);
|
||||
config.setTokenUrl(baseUrl + TOKEN_RESOURCE);
|
||||
config.setUserInfoUrl(baseUrl + PROFILE_RESOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultScopes() {
|
||||
return DEFAULT_SCOPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||
try {
|
||||
final JsonNode profile = fetchProfile(accessToken);
|
||||
final BrokeredIdentityContext user = extractUserContext(profile.get("metadata"));
|
||||
AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
|
||||
return user;
|
||||
} catch (Exception e) {
|
||||
throw new IdentityBrokerException("Could not obtain user profile from Openshift.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private BrokeredIdentityContext extractUserContext(JsonNode metadata) {
|
||||
final BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(metadata, "uid"));
|
||||
user.setUsername(getJsonProperty(metadata, "name"));
|
||||
user.setName(getJsonProperty(metadata, "fullName"));
|
||||
user.setIdpConfig(getConfig());
|
||||
user.setIdp(this);
|
||||
return user;
|
||||
}
|
||||
|
||||
private JsonNode fetchProfile(String accessToken) throws IOException {
|
||||
return JsonSimpleHttp.asJson(SimpleHttp.doGet(getConfig().getUserInfoUrl())
|
||||
.header("Authorization", "Bearer " + accessToken));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.keycloak.social.openshift;
|
||||
|
||||
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
||||
import org.keycloak.broker.social.SocialIdentityProviderFactory;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
public class OpenshiftV3IdentityProviderFactory extends AbstractIdentityProviderFactory<OpenshiftV3IdentityProvider> implements SocialIdentityProviderFactory<OpenshiftV3IdentityProvider> {
|
||||
|
||||
public static final String PROVIDER_ID = "openshift-v3";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Openshift v3";
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenshiftV3IdentityProvider create(KeycloakSession keycloakSession, IdentityProviderModel identityProviderModel) {
|
||||
return new OpenshiftV3IdentityProvider(keycloakSession, new OpenshifV3IdentityProviderConfig(identityProviderModel));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
}
|
|
@ -22,3 +22,4 @@ org.keycloak.social.linkedin.LinkedInIdentityProviderFactory
|
|||
org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory
|
||||
org.keycloak.social.twitter.TwitterIdentityProviderFactory
|
||||
org.keycloak.social.microsoft.MicrosoftIdentityProviderFactory
|
||||
org.keycloak.social.openshift.OpenshiftV3IdentityProviderFactory
|
||||
|
|
|
@ -37,6 +37,9 @@ import org.keycloak.social.google.GoogleIdentityProvider;
|
|||
import org.keycloak.social.google.GoogleIdentityProviderFactory;
|
||||
import org.keycloak.social.linkedin.LinkedInIdentityProvider;
|
||||
import org.keycloak.social.linkedin.LinkedInIdentityProviderFactory;
|
||||
import org.keycloak.social.openshift.OpenshifV3IdentityProviderConfig;
|
||||
import org.keycloak.social.openshift.OpenshiftV3IdentityProvider;
|
||||
import org.keycloak.social.openshift.OpenshiftV3IdentityProviderFactory;
|
||||
import org.keycloak.social.stackoverflow.StackOverflowIdentityProviderConfig;
|
||||
import org.keycloak.social.stackoverflow.StackoverflowIdentityProvider;
|
||||
import org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory;
|
||||
|
@ -146,6 +149,8 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertLinkedInIdentityProviderConfig(identityProvider);
|
||||
} else if (StackoverflowIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertStackoverflowIdentityProviderConfig(identityProvider);
|
||||
} else if (OpenshiftV3IdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertOpenshiftIdentityProviderConfig(identityProvider);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
@ -283,6 +288,21 @@ public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTes
|
|||
assertEquals(StackoverflowIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
}
|
||||
|
||||
private void assertOpenshiftIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
OpenshiftV3IdentityProvider osoIdentityProvider = new OpenshiftV3IdentityProviderFactory().create(session, identityProvider);
|
||||
OpenshifV3IdentityProviderConfig config = osoIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-openshift-v3", config.getAlias());
|
||||
assertEquals(OpenshiftV3IdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(false, config.isTrustEmail());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
assertEquals(OpenshiftV3IdentityProvider.BASE_URL, config.getBaseUrl());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
}
|
||||
|
||||
private void assertTwitterIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
TwitterIdentityProvider twitterIdentityProvider = new TwitterIdentityProviderFactory().create(session, identityProvider);
|
||||
OAuth2IdentityProviderConfig config = twitterIdentityProvider.getConfig();
|
||||
|
|
|
@ -91,6 +91,20 @@
|
|||
"clientSecret": "clientSecret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"alias" : "model-openshift-v3",
|
||||
"providerId" : "openshift-v3",
|
||||
"enabled": true,
|
||||
"storeToken": true,
|
||||
"config": {
|
||||
"baseUrl": "https://api.preview.openshift.com",
|
||||
"authorizationUrl": "authorizationUrl",
|
||||
"tokenUrl": "tokenUrl",
|
||||
"userInfoUrl": "userInfoUrl",
|
||||
"clientId": "clientId",
|
||||
"clientSecret": "clientSecret"
|
||||
}
|
||||
},
|
||||
{
|
||||
"alias" : "model-saml-signed-idp",
|
||||
"providerId" : "saml",
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<div class="form-group clearfix">
|
||||
<label class="col-md-2 control-label" for="baseUrl"><span class="required">*</span> {{:: 'Base URL' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" id="baseUrl" type="text" ng-model="identityProvider.config.baseUrl" required>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1 @@
|
|||
<div data-ng-include data-src="resourceUrl + '/partials/realm-identity-provider-social.html'"></div>
|
Loading…
Reference in a new issue