commit
aee47a80bd
20 changed files with 723 additions and 509 deletions
|
@ -16,6 +16,8 @@ public class ProtocolMapperTypeRepresentation {
|
|||
protected String name;
|
||||
protected String label;
|
||||
protected String helpText;
|
||||
protected String type;
|
||||
protected String defaultValue;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -33,6 +35,22 @@ public class ProtocolMapperTypeRepresentation {
|
|||
this.label = label;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(String defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public String getHelpText() {
|
||||
return helpText;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ module.controller('ProtocolMapperCtrl', function($scope, realm, serverInfo, prot
|
|||
$scope.mapper = angular.copy(mapper);
|
||||
var oldCopy = angular.copy($scope.realm);
|
||||
$scope.changed = false;
|
||||
$scope.boolval = true;
|
||||
$scope.boolvalId = 'boolval';
|
||||
|
||||
console.log('protocol: ' + protocol);
|
||||
var protocolMappers = serverInfo.protocolMapperTypes[protocol];
|
||||
|
|
|
@ -76,9 +76,12 @@
|
|||
<div data-ng-repeat="option in mapperType.properties" class="form-group">
|
||||
<label class="col-sm-2 control-label">{{option.label}} </label>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<div class="col-sm-4" data-ng-hide="option.type == 'boolean'">
|
||||
<input class="form-control" type="text" data-ng-model="mapper.config[ option.name ]" >
|
||||
</div>
|
||||
<div class="col-sm-4" data-ng-show="option.type == 'boolean'">
|
||||
<input ng-model="mapper.config[ option.name ]" value="'true'" name="option.name" id="option.name" onoffswitchmodel />
|
||||
</div>
|
||||
<span tooltip-placement="right" tooltip="{{option.helpText}}" class="fa fa-info-circle"></span>
|
||||
</div>
|
||||
|
||||
|
|
0
model/api/src/main/java/org/keycloak/models/entities/ClientIdentityProviderMappingEntity.java
Normal file → Executable file
0
model/api/src/main/java/org/keycloak/models/entities/ClientIdentityProviderMappingEntity.java
Normal file → Executable file
|
@ -457,12 +457,6 @@ public class RepresentationToModel {
|
|||
applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
|
||||
}
|
||||
|
||||
if (resourceRep.getClaims() != null) {
|
||||
setClaims(applicationModel, resourceRep.getClaims());
|
||||
} else {
|
||||
applicationModel.setAllowedClaimsMask(ClaimMask.ALL);
|
||||
}
|
||||
|
||||
if (resourceRep.getProtocolMappers() != null) {
|
||||
Set<String> ids = new HashSet<String>();
|
||||
for (ClientProtocolMappingRepresentation map : resourceRep.getProtocolMappers()) {
|
||||
|
@ -524,10 +518,6 @@ public class RepresentationToModel {
|
|||
}
|
||||
}
|
||||
|
||||
if (rep.getClaims() != null) {
|
||||
setClaims(resource, rep.getClaims());
|
||||
}
|
||||
|
||||
updateClientIdentityProvides(rep.getIdentityProviders(), resource);
|
||||
}
|
||||
|
||||
|
@ -633,10 +623,6 @@ public class RepresentationToModel {
|
|||
model.setWebOrigins(new HashSet<String>(webOrigins));
|
||||
}
|
||||
|
||||
if (rep.getClaims() != null) {
|
||||
setClaims(model, rep.getClaims());
|
||||
}
|
||||
|
||||
if (rep.getNotBefore() != null) {
|
||||
model.setNotBefore(rep.getNotBefore());
|
||||
}
|
||||
|
|
|
@ -16,9 +16,14 @@ public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper
|
|||
String getHelpText();
|
||||
|
||||
public static class ConfigProperty {
|
||||
public static final String BOOLEAN_TYPE="boolean";
|
||||
public static final String STRING_TYPE="String";
|
||||
|
||||
protected String name;
|
||||
protected String label;
|
||||
protected String helpText;
|
||||
protected String type;
|
||||
protected String defaultValue;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -36,6 +41,22 @@ public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper
|
|||
this.label = label;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(String defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public String getHelpText() {
|
||||
return helpText;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,16 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.AbstractLoginProtocolFactory;
|
||||
import org.keycloak.protocol.LoginProtocol;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAddressMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCFullNameMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCUserModelMapper;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -29,27 +34,32 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
|
|||
"username",
|
||||
"preferred_username", "String",
|
||||
true, "username",
|
||||
true);
|
||||
true,
|
||||
true, true);
|
||||
OIDCUserModelMapper.addClaimMapper(realm, "email",
|
||||
"email",
|
||||
"email", "String",
|
||||
true, "email",
|
||||
true);
|
||||
true,
|
||||
true, true);
|
||||
OIDCUserModelMapper.addClaimMapper(realm, "given name",
|
||||
"firstName",
|
||||
"given_name", "String",
|
||||
true, "given name",
|
||||
true);
|
||||
true,
|
||||
true, true);
|
||||
OIDCUserModelMapper.addClaimMapper(realm, "family name",
|
||||
"lastName",
|
||||
"family_name", "String",
|
||||
true, "family name",
|
||||
true);
|
||||
true,
|
||||
true, true);
|
||||
OIDCUserModelMapper.addClaimMapper(realm, "email verified",
|
||||
"emailVerified",
|
||||
"email_verified", "boolean",
|
||||
false, null,
|
||||
false);
|
||||
false,
|
||||
true, true);
|
||||
|
||||
ProtocolMapperModel fullName = new ProtocolMapperModel();
|
||||
if (realm.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "full name") == null) {
|
||||
|
@ -59,6 +69,10 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
|
|||
fullName.setConsentRequired(true);
|
||||
fullName.setConsentText("full name");
|
||||
fullName.setAppliedByDefault(true);
|
||||
Map<String, String> config = new HashMap<String, String>();
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
fullName.setConfig(config);
|
||||
realm.addProtocolMapper(fullName);
|
||||
}
|
||||
|
||||
|
@ -70,6 +84,10 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
|
|||
address.setConsentRequired(true);
|
||||
address.setConsentText("address");
|
||||
address.setAppliedByDefault(false);
|
||||
Map<String, String> config = new HashMap<String, String>();
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
address.setConfig(config);
|
||||
realm.addProtocolMapper(address);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.keycloak.jose.jws.JWSBuilder;
|
|||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClaimMask;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
@ -25,7 +24,6 @@ import org.keycloak.protocol.ProtocolMapper;
|
|||
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.UserClaimSet;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
|
@ -244,7 +242,7 @@ public class TokenManager {
|
|||
|
||||
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
|
||||
if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue;
|
||||
token = ((OIDCAccessTokenMapper)mapper).transformToken(token, mapping, session, userSession, clientSession);
|
||||
token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,154 +1,154 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.protocol.oidc;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.UserClaimSet;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.EventsManager;
|
||||
import org.keycloak.services.resources.Cors;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.OPTIONS;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public class UserInfoService {
|
||||
|
||||
@Context
|
||||
private HttpRequest request;
|
||||
|
||||
@Context
|
||||
private HttpResponse response;
|
||||
|
||||
@Context
|
||||
private KeycloakSession session;
|
||||
|
||||
@Context
|
||||
private ClientConnection clientConnection;
|
||||
|
||||
private final TokenManager tokenManager;
|
||||
private final AppAuthManager appAuthManager;
|
||||
private final OIDCLoginProtocolService openIdConnectService;
|
||||
private final RealmModel realmModel;
|
||||
|
||||
public UserInfoService(OIDCLoginProtocolService openIDConnectService) {
|
||||
this.realmModel = openIDConnectService.getRealm();
|
||||
|
||||
if (this.realmModel == null) {
|
||||
throw new RuntimeException("Null realm.");
|
||||
}
|
||||
|
||||
this.tokenManager = openIDConnectService.getTokenManager();
|
||||
|
||||
if (this.tokenManager == null) {
|
||||
throw new RuntimeException("Null token manager.");
|
||||
}
|
||||
|
||||
this.openIdConnectService = openIDConnectService;
|
||||
this.appAuthManager = new AppAuthManager();
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@OPTIONS
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoPreflight() {
|
||||
return Cors.add(this.request, Response.ok()).auth().preflight().build();
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoGet(@Context final HttpHeaders headers) {
|
||||
String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
|
||||
return issueUserInfo(accessToken);
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@POST
|
||||
@NoCache
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
|
||||
return issueUserInfo(accessToken);
|
||||
}
|
||||
|
||||
private Response issueUserInfo(String token) {
|
||||
try {
|
||||
EventBuilder event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder()
|
||||
.event(EventType.USER_INFO_REQUEST)
|
||||
.detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
|
||||
|
||||
Response validationResponse = this.openIdConnectService.validateAccessToken(token);
|
||||
|
||||
if (!AccessToken.class.isInstance(validationResponse.getEntity())) {
|
||||
event.error(EventType.USER_INFO_REQUEST.name());
|
||||
return Response.fromResponse(validationResponse).status(Status.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
AccessToken accessToken = (AccessToken) validationResponse.getEntity();
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realmModel, accessToken.getSessionState());
|
||||
ClientModel clientModel = realmModel.findClient(accessToken.getIssuedFor());
|
||||
UserModel userModel = userSession.getUser();
|
||||
AccessToken userInfo = new AccessToken();
|
||||
this.tokenManager.transformToken(session, userInfo, realmModel, clientModel, userModel, userSession, null);
|
||||
|
||||
event
|
||||
.detail(Details.USERNAME, userModel.getUsername())
|
||||
.client(clientModel)
|
||||
.session(userSession)
|
||||
.user(userModel)
|
||||
.success();
|
||||
|
||||
Map<String, Object> claims = new HashMap<String, Object>();
|
||||
claims.putAll(userInfo.getOtherClaims());
|
||||
claims.put("sub", userModel.getId());
|
||||
return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(accessToken).build();
|
||||
} catch (Exception e) {
|
||||
throw new UnauthorizedException("Could not retrieve user info.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.protocol.oidc;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.jboss.resteasy.spi.HttpResponse;
|
||||
import org.jboss.resteasy.spi.UnauthorizedException;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.UserClaimSet;
|
||||
import org.keycloak.services.managers.AppAuthManager;
|
||||
import org.keycloak.services.managers.EventsManager;
|
||||
import org.keycloak.services.resources.Cors;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.OPTIONS;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public class UserInfoService {
|
||||
|
||||
@Context
|
||||
private HttpRequest request;
|
||||
|
||||
@Context
|
||||
private HttpResponse response;
|
||||
|
||||
@Context
|
||||
private KeycloakSession session;
|
||||
|
||||
@Context
|
||||
private ClientConnection clientConnection;
|
||||
|
||||
private final TokenManager tokenManager;
|
||||
private final AppAuthManager appAuthManager;
|
||||
private final OIDCLoginProtocolService openIdConnectService;
|
||||
private final RealmModel realmModel;
|
||||
|
||||
public UserInfoService(OIDCLoginProtocolService openIDConnectService) {
|
||||
this.realmModel = openIDConnectService.getRealm();
|
||||
|
||||
if (this.realmModel == null) {
|
||||
throw new RuntimeException("Null realm.");
|
||||
}
|
||||
|
||||
this.tokenManager = openIDConnectService.getTokenManager();
|
||||
|
||||
if (this.tokenManager == null) {
|
||||
throw new RuntimeException("Null token manager.");
|
||||
}
|
||||
|
||||
this.openIdConnectService = openIDConnectService;
|
||||
this.appAuthManager = new AppAuthManager();
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@OPTIONS
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoPreflight() {
|
||||
return Cors.add(this.request, Response.ok()).auth().preflight().build();
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoGet(@Context final HttpHeaders headers) {
|
||||
String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
|
||||
return issueUserInfo(accessToken);
|
||||
}
|
||||
|
||||
@Path("/")
|
||||
@POST
|
||||
@NoCache
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
|
||||
return issueUserInfo(accessToken);
|
||||
}
|
||||
|
||||
private Response issueUserInfo(String token) {
|
||||
try {
|
||||
EventBuilder event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder()
|
||||
.event(EventType.USER_INFO_REQUEST)
|
||||
.detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
|
||||
|
||||
Response validationResponse = this.openIdConnectService.validateAccessToken(token);
|
||||
|
||||
if (!AccessToken.class.isInstance(validationResponse.getEntity())) {
|
||||
event.error(EventType.USER_INFO_REQUEST.name());
|
||||
return Response.fromResponse(validationResponse).status(Status.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
AccessToken accessToken = (AccessToken) validationResponse.getEntity();
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realmModel, accessToken.getSessionState());
|
||||
ClientModel clientModel = realmModel.findClient(accessToken.getIssuedFor());
|
||||
UserModel userModel = userSession.getUser();
|
||||
AccessToken userInfo = new AccessToken();
|
||||
this.tokenManager.transformToken(session, userInfo, realmModel, clientModel, userModel, userSession, null);
|
||||
|
||||
event
|
||||
.detail(Details.USERNAME, userModel.getUsername())
|
||||
.client(clientModel)
|
||||
.session(userSession)
|
||||
.user(userModel)
|
||||
.success();
|
||||
|
||||
Map<String, Object> claims = new HashMap<String, Object>();
|
||||
claims.putAll(userInfo.getOtherClaims());
|
||||
claims.put("sub", userModel.getId());
|
||||
return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(accessToken).build();
|
||||
} catch (Exception e) {
|
||||
throw new UnauthorizedException("Could not retrieve user info.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@ import org.keycloak.representations.AccessToken;
|
|||
*/
|
||||
public interface OIDCAccessTokenMapper {
|
||||
|
||||
AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession);
|
||||
AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.UserClaimSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -17,12 +18,26 @@ import java.util.List;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||
public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
static {
|
||||
|
||||
ConfigProperty property;
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
}
|
||||
|
||||
public static final String PROVIDER_ID = "oidc-address-mapper";
|
||||
|
@ -53,8 +68,21 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
|
||||
setClaim(token, userSession);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
|
||||
setClaim(token, userSession);
|
||||
return token;
|
||||
}
|
||||
|
||||
protected void setClaim(IDToken token, UserSessionModel userSession) {
|
||||
UserModel user = userSession.getUser();
|
||||
UserClaimSet.AddressClaimSet addressSet = new UserClaimSet.AddressClaimSet();
|
||||
addressSet.setStreetAddress(user.getAttribute("street"));
|
||||
|
@ -63,7 +91,6 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID
|
|||
addressSet.setPostalCode(user.getAttribute("postal_code"));
|
||||
addressSet.setCountry(user.getAttribute("country"));
|
||||
token.getOtherClaims().put("address", addressSet);
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.keycloak.models.RealmModel;
|
|||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -16,6 +17,12 @@ import java.util.Map;
|
|||
public class OIDCAttributeMapperHelper {
|
||||
public static final String TOKEN_CLAIM_NAME = "Token Claim Name";
|
||||
public static final String JSON_TYPE = "Claim JSON Type";
|
||||
public static final String INCLUDE_IN_ACCESS_TOKEN = "access.token.claim";
|
||||
public static final String INCLUDE_IN_ACCESS_TOKEN_LABEL = "Add to access token";
|
||||
public static final String INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT = "Should the claim be added to the access token?";
|
||||
public static final String INCLUDE_IN_ID_TOKEN = "id.token.claim";
|
||||
public static final String INCLUDE_IN_ID_TOKEN_LABEL = "Add to ID token";
|
||||
public static final String INCLUDE_IN_ID_TOKEN_HELP_TEXT = "Should the claim be added to the ID token?";
|
||||
|
||||
public static Object mapAttributeValue(ProtocolMapperModel mappingModel, Object attributeValue) {
|
||||
if (attributeValue == null) return null;
|
||||
|
@ -40,7 +47,7 @@ public class OIDCAttributeMapperHelper {
|
|||
return attributeValue;
|
||||
}
|
||||
|
||||
public static void mapClaim(AccessToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
|
||||
public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
|
||||
if (attributeValue == null) return;
|
||||
attributeValue = mapAttributeValue(mappingModel, attributeValue);
|
||||
String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME);
|
||||
|
@ -65,6 +72,7 @@ public class OIDCAttributeMapperHelper {
|
|||
String tokenClaimName, String claimType,
|
||||
boolean consentRequired, String consentText,
|
||||
boolean appliedByDefault,
|
||||
boolean accessToken, boolean idToken,
|
||||
String mapperId) {
|
||||
ProtocolMapperModel mapper = realm.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, name);
|
||||
if (mapper != null) return;
|
||||
|
@ -79,7 +87,17 @@ public class OIDCAttributeMapperHelper {
|
|||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
|
||||
config.put(TOKEN_CLAIM_NAME, tokenClaimName);
|
||||
config.put(JSON_TYPE, claimType);
|
||||
if (accessToken) config.put(INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
if (idToken) config.put(INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
realm.addProtocolMapper(mapper);
|
||||
}
|
||||
|
||||
public static boolean includeInIDToken(ProtocolMapperModel mappingModel) {
|
||||
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ID_TOKEN));
|
||||
}
|
||||
|
||||
public static boolean includeInAccessToken(ProtocolMapperModel mappingModel) {
|
||||
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -16,11 +17,26 @@ import java.util.List;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||
public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
static {
|
||||
ConfigProperty property;
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
|
||||
}
|
||||
|
||||
|
@ -52,13 +68,24 @@ public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OI
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
|
||||
setClaim(token, userSession);
|
||||
return token;
|
||||
}
|
||||
|
||||
protected void setClaim(IDToken token, UserSessionModel userSession) {
|
||||
UserModel user = userSession.getUser();
|
||||
String first = user.getFirstName() == null ? "" : user.getFirstName() + " ";
|
||||
String last = user.getLastName() == null ? "" : user.getLastName();
|
||||
token.getOtherClaims().put("name", first + last);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
|
||||
setClaim(token, userSession);
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.keycloak.protocol.oidc.mappers;
|
||||
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface OIDCIDTokenMapper {
|
||||
|
||||
IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession);
|
||||
}
|
|
@ -8,6 +8,7 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -20,7 +21,7 @@ import java.util.List;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||
public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
|
@ -30,12 +31,35 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
|
|||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setDefaultValue(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
|
||||
}
|
||||
|
||||
|
@ -67,13 +91,26 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
|
||||
|
||||
setClaim(token, mappingModel, userSession);
|
||||
return token;
|
||||
}
|
||||
|
||||
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
|
||||
UserModel user = userSession.getUser();
|
||||
String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||
String attributeValue = user.getAttribute(attributeName);
|
||||
if (attributeValue == null) return token;
|
||||
if (attributeValue == null) return;
|
||||
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
|
||||
setClaim(token, mappingModel, userSession);
|
||||
return token;
|
||||
}
|
||||
|
||||
|
@ -81,11 +118,13 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
|
|||
String userAttribute,
|
||||
String tokenClaimName, String claimType,
|
||||
boolean consentRequired, String consentText,
|
||||
boolean appliedByDefault) {
|
||||
boolean appliedByDefault,
|
||||
boolean accessToken, boolean idToken) {
|
||||
OIDCAttributeMapperHelper.addClaimMapper(realm, name, userAttribute,
|
||||
tokenClaimName, claimType,
|
||||
consentRequired, consentText,
|
||||
appliedByDefault, PROVIDER_ID);
|
||||
appliedByDefault, accessToken, idToken,
|
||||
PROVIDER_ID);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -20,7 +21,7 @@ import java.util.List;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||
public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
static {
|
||||
|
@ -28,14 +29,36 @@ public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements O
|
|||
property = new ConfigProperty();
|
||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
||||
configProperties.add(property);
|
||||
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setDefaultValue(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
property = new ConfigProperty();
|
||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
||||
property.setDefaultValue("true");
|
||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
}
|
||||
|
||||
public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
|
||||
|
@ -66,25 +89,40 @@ public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements O
|
|||
}
|
||||
|
||||
@Override
|
||||
public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
|
||||
UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
|
||||
setClaim(token, mappingModel, userSession);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
|
||||
setClaim(token, mappingModel, userSession);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
|
||||
UserModel user = userSession.getUser();
|
||||
String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||
String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
|
||||
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, propertyValue);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public static void addClaimMapper(RealmModel realm, String name,
|
||||
String userAttribute,
|
||||
String tokenClaimName, String claimType,
|
||||
boolean consentRequired, String consentText,
|
||||
boolean appliedByDefault) {
|
||||
boolean appliedByDefault,
|
||||
boolean accessToken, boolean idToken) {
|
||||
OIDCAttributeMapperHelper.addClaimMapper(realm, name, userAttribute,
|
||||
tokenClaimName, claimType,
|
||||
consentRequired, consentText,
|
||||
appliedByDefault, PROVIDER_ID);
|
||||
appliedByDefault, accessToken, idToken,
|
||||
PROVIDER_ID);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -150,6 +150,8 @@ public class ServerInfoAdminResource {
|
|||
ProtocolMapperTypeRepresentation.ConfigProperty propRep = new ProtocolMapperTypeRepresentation.ConfigProperty();
|
||||
propRep.setName(prop.getName());
|
||||
propRep.setLabel(prop.getLabel());
|
||||
propRep.setType(prop.getType());
|
||||
propRep.setDefaultValue(prop.getDefaultValue());
|
||||
propRep.setHelpText(prop.getHelpText());
|
||||
rep.getProperties().add(propRep);
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ public class AccountTest {
|
|||
});
|
||||
}
|
||||
|
||||
//@Test @Ignore
|
||||
@Test @Ignore
|
||||
public void runit() throws Exception {
|
||||
Thread.sleep(10000000);
|
||||
}
|
||||
|
|
|
@ -214,10 +214,6 @@ public class AdminAPITest {
|
|||
|
||||
Assert.assertEquals(set, storedSet);
|
||||
}
|
||||
|
||||
if (appRep.getClaims() != null) {
|
||||
Assert.assertEquals(appRep.getClaims(), storedApp.getClaims());
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkRealmRep(RealmRepresentation rep, RealmRepresentation storedRealm) {
|
||||
|
|
605
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
Normal file → Executable file
605
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/ImportIdentityProviderTest.java
Normal file → Executable file
|
@ -1,301 +1,304 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.testsuite.broker;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProvider;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProvider;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
|
||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProvider;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
|
||||
import org.keycloak.social.github.GitHubIdentityProvider;
|
||||
import org.keycloak.social.github.GitHubIdentityProviderFactory;
|
||||
import org.keycloak.social.google.GoogleIdentityProvider;
|
||||
import org.keycloak.social.google.GoogleIdentityProviderFactory;
|
||||
import org.keycloak.social.twitter.TwitterIdentityProvider;
|
||||
import org.keycloak.social.twitter.TwitterIdentityProviderFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTest {
|
||||
|
||||
@Test
|
||||
public void testInstallation() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
|
||||
assertIdentityProviderConfig(realm.getIdentityProviders());
|
||||
|
||||
assertTrue(realm.isIdentityFederationEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateIdentityProvider() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
|
||||
|
||||
assertFalse(identityProviders.isEmpty());
|
||||
|
||||
IdentityProviderModel identityProviderModel = identityProviders.get(0);
|
||||
String identityProviderId = identityProviderModel.getId();
|
||||
|
||||
identityProviderModel.setName("Changed Name");
|
||||
identityProviderModel.getConfig().put("config-added", "value-added");
|
||||
identityProviderModel.setEnabled(false);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setStoreToken(true);
|
||||
identityProviderModel.setAuthenticateByDefault(true);
|
||||
|
||||
realm.updateIdentityProvider(identityProviderModel);
|
||||
|
||||
commit();
|
||||
|
||||
realm = this.realmManager.getRealm(realm.getId());
|
||||
|
||||
identityProviderModel = realm.getIdentityProviderById(identityProviderId);
|
||||
|
||||
assertEquals("Changed Name", identityProviderModel.getName());
|
||||
assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
|
||||
assertFalse(identityProviderModel.isEnabled());
|
||||
assertFalse(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertTrue(identityProviderModel.isStoreToken());
|
||||
assertTrue(identityProviderModel.isAuthenticateByDefault());
|
||||
|
||||
identityProviderModel.setName("Changed Name Again");
|
||||
identityProviderModel.getConfig().remove("config-added");
|
||||
identityProviderModel.setEnabled(true);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setAuthenticateByDefault(false);
|
||||
|
||||
realm.updateIdentityProvider(identityProviderModel);
|
||||
|
||||
commit();
|
||||
|
||||
realm = this.realmManager.getRealm(realm.getId());
|
||||
identityProviderModel = realm.getIdentityProviderById(identityProviderId);
|
||||
|
||||
assertEquals("Changed Name Again", identityProviderModel.getName());
|
||||
assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
|
||||
assertTrue(identityProviderModel.isEnabled());
|
||||
assertTrue(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertFalse(identityProviderModel.isAuthenticateByDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplicationIdentityProviders() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
|
||||
ClientModel client = realm.findClient("test-app-with-allowed-providers");
|
||||
List<ClientIdentityProviderMappingModel> identityProviders = client.getIdentityProviders();
|
||||
|
||||
assertEquals(1, identityProviders.size());
|
||||
|
||||
ClientIdentityProviderMappingModel identityProviderMappingModel = identityProviders.get(0);
|
||||
|
||||
assertEquals("kc-oidc-idp", identityProviderMappingModel.getIdentityProvider());
|
||||
assertEquals(false, identityProviderMappingModel.isRetrieveToken());
|
||||
|
||||
identityProviders.remove(identityProviderMappingModel);
|
||||
|
||||
client.updateAllowedIdentityProviders(identityProviders);
|
||||
|
||||
client = realm.findClientById(client.getId());
|
||||
identityProviders = client.getIdentityProviders();
|
||||
|
||||
assertEquals(0, identityProviders.size());
|
||||
}
|
||||
|
||||
|
||||
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
|
||||
assertFalse(identityProviders.isEmpty());
|
||||
|
||||
Set<String> checkedProviders = new HashSet<String>(getExpectedProviders());
|
||||
|
||||
for (IdentityProviderModel identityProvider : identityProviders) {
|
||||
if (identityProvider.getId().startsWith("model-")) {
|
||||
String providerId = identityProvider.getProviderId();
|
||||
|
||||
if (SAMLIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertSamlIdentityProviderConfig(identityProvider);
|
||||
} else if (GoogleIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertGoogleIdentityProviderConfig(identityProvider);
|
||||
} else if (OIDCIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertOidcIdentityProviderConfig(identityProvider);
|
||||
} else if (FacebookIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertFacebookIdentityProviderConfig(identityProvider);
|
||||
} else if (GitHubIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertGitHubIdentityProviderConfig(identityProvider);
|
||||
} else if (TwitterIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertTwitterIdentityProviderConfig(identityProvider);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
checkedProviders.remove(providerId);
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(checkedProviders.isEmpty());
|
||||
}
|
||||
|
||||
private void assertGoogleIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
GoogleIdentityProvider googleIdentityProvider = new GoogleIdentityProviderFactory().create(identityProvider);
|
||||
OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-google", config.getId());
|
||||
assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Google", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(GoogleIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(GoogleIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(GoogleIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
|
||||
}
|
||||
|
||||
private void assertSamlIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
SAMLIdentityProvider samlIdentityProvider = new SAMLIdentityProviderFactory().create(identityProvider);
|
||||
SAMLIdentityProviderConfig config = samlIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-saml-signed-idp", config.getId());
|
||||
assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("SAML Signed IdP", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl());
|
||||
assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat());
|
||||
assertEquals("MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin", config.getSigningCertificate());
|
||||
assertEquals(true, config.isWantAuthnRequestsSigned());
|
||||
assertEquals(true, config.isForceAuthn());
|
||||
assertEquals(true, config.isPostBindingAuthnRequest());
|
||||
assertEquals(true, config.isPostBindingResponse());
|
||||
assertEquals(true, config.isValidateSignature());
|
||||
}
|
||||
|
||||
private void assertOidcIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
OIDCIdentityProvider googleIdentityProvider = new OIDCIdentityProviderFactory().create(identityProvider);
|
||||
OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-oidc-idp", config.getId());
|
||||
assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("OIDC IdP", config.getName());
|
||||
assertEquals(false, config.isEnabled());
|
||||
assertEquals(false, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
}
|
||||
|
||||
private void assertFacebookIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
FacebookIdentityProvider facebookIdentityProvider = new FacebookIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = facebookIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-facebook", config.getId());
|
||||
assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Facebook", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(FacebookIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(FacebookIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(FacebookIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
}
|
||||
|
||||
private void assertGitHubIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
GitHubIdentityProvider gitHubIdentityProvider = new GitHubIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = gitHubIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-github", config.getId());
|
||||
assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("GitHub", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(GitHubIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(GitHubIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(GitHubIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
}
|
||||
|
||||
private void assertTwitterIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
TwitterIdentityProvider twitterIdentityProvider = new TwitterIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = twitterIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-twitter", config.getId());
|
||||
assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Twitter", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
}
|
||||
|
||||
private RealmModel installTestRealm() throws IOException {
|
||||
RealmRepresentation realmRepresentation = loadJson("broker-test/test-realm-with-broker.json");
|
||||
|
||||
assertNotNull(realmRepresentation);
|
||||
assertEquals("realm-with-broker", realmRepresentation.getRealm());
|
||||
|
||||
RealmModel realmModel = this.realmManager.getRealm("realm-with-broker");
|
||||
|
||||
if (realmModel == null) {
|
||||
realmModel = this.realmManager.importRealm(realmRepresentation);
|
||||
|
||||
commit();
|
||||
|
||||
realmModel = this.realmManager.getRealm(realmModel.getId());
|
||||
|
||||
assertNotNull(realmModel);
|
||||
}
|
||||
|
||||
return realmModel;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
*
|
||||
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||
*
|
||||
* 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.testsuite.broker;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProvider;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProvider;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
|
||||
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
|
||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProvider;
|
||||
import org.keycloak.social.facebook.FacebookIdentityProviderFactory;
|
||||
import org.keycloak.social.github.GitHubIdentityProvider;
|
||||
import org.keycloak.social.github.GitHubIdentityProviderFactory;
|
||||
import org.keycloak.social.google.GoogleIdentityProvider;
|
||||
import org.keycloak.social.google.GoogleIdentityProviderFactory;
|
||||
import org.keycloak.social.twitter.TwitterIdentityProvider;
|
||||
import org.keycloak.social.twitter.TwitterIdentityProviderFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
*/
|
||||
public class ImportIdentityProviderTest extends AbstractIdentityProviderModelTest {
|
||||
|
||||
@Test
|
||||
public void testInstallation() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
|
||||
assertIdentityProviderConfig(realm.getIdentityProviders());
|
||||
|
||||
assertTrue(realm.isIdentityFederationEnabled());
|
||||
this.realmManager.removeRealm(realm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateIdentityProvider() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
|
||||
|
||||
assertFalse(identityProviders.isEmpty());
|
||||
|
||||
IdentityProviderModel identityProviderModel = identityProviders.get(0);
|
||||
String identityProviderId = identityProviderModel.getId();
|
||||
|
||||
identityProviderModel.setName("Changed Name");
|
||||
identityProviderModel.getConfig().put("config-added", "value-added");
|
||||
identityProviderModel.setEnabled(false);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(false);
|
||||
identityProviderModel.setStoreToken(true);
|
||||
identityProviderModel.setAuthenticateByDefault(true);
|
||||
|
||||
realm.updateIdentityProvider(identityProviderModel);
|
||||
|
||||
commit();
|
||||
|
||||
realm = this.realmManager.getRealm(realm.getId());
|
||||
|
||||
identityProviderModel = realm.getIdentityProviderById(identityProviderId);
|
||||
|
||||
assertEquals("Changed Name", identityProviderModel.getName());
|
||||
assertEquals("value-added", identityProviderModel.getConfig().get("config-added"));
|
||||
assertFalse(identityProviderModel.isEnabled());
|
||||
assertFalse(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertTrue(identityProviderModel.isStoreToken());
|
||||
assertTrue(identityProviderModel.isAuthenticateByDefault());
|
||||
|
||||
identityProviderModel.setName("Changed Name Again");
|
||||
identityProviderModel.getConfig().remove("config-added");
|
||||
identityProviderModel.setEnabled(true);
|
||||
identityProviderModel.setUpdateProfileFirstLogin(true);
|
||||
identityProviderModel.setAuthenticateByDefault(false);
|
||||
|
||||
realm.updateIdentityProvider(identityProviderModel);
|
||||
|
||||
commit();
|
||||
|
||||
realm = this.realmManager.getRealm(realm.getId());
|
||||
identityProviderModel = realm.getIdentityProviderById(identityProviderId);
|
||||
|
||||
assertEquals("Changed Name Again", identityProviderModel.getName());
|
||||
assertFalse(identityProviderModel.getConfig().containsKey("config-added"));
|
||||
assertTrue(identityProviderModel.isEnabled());
|
||||
assertTrue(identityProviderModel.isUpdateProfileFirstLogin());
|
||||
assertFalse(identityProviderModel.isAuthenticateByDefault());
|
||||
this.realmManager.removeRealm(realm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplicationIdentityProviders() throws Exception {
|
||||
RealmModel realm = installTestRealm();
|
||||
|
||||
ClientModel client = realm.findClient("test-app-with-allowed-providers");
|
||||
List<ClientIdentityProviderMappingModel> identityProviders = client.getIdentityProviders();
|
||||
|
||||
assertEquals(1, identityProviders.size());
|
||||
|
||||
ClientIdentityProviderMappingModel identityProviderMappingModel = identityProviders.get(0);
|
||||
|
||||
assertEquals("kc-oidc-idp", identityProviderMappingModel.getIdentityProvider());
|
||||
assertEquals(false, identityProviderMappingModel.isRetrieveToken());
|
||||
|
||||
identityProviders.remove(identityProviderMappingModel);
|
||||
|
||||
client.updateAllowedIdentityProviders(identityProviders);
|
||||
|
||||
client = realm.findClientById(client.getId());
|
||||
identityProviders = client.getIdentityProviders();
|
||||
|
||||
assertEquals(0, identityProviders.size());
|
||||
this.realmManager.removeRealm(realm);
|
||||
}
|
||||
|
||||
|
||||
private void assertIdentityProviderConfig(List<IdentityProviderModel> identityProviders) {
|
||||
assertFalse(identityProviders.isEmpty());
|
||||
|
||||
Set<String> checkedProviders = new HashSet<String>(getExpectedProviders());
|
||||
|
||||
for (IdentityProviderModel identityProvider : identityProviders) {
|
||||
if (identityProvider.getId().startsWith("model-")) {
|
||||
String providerId = identityProvider.getProviderId();
|
||||
|
||||
if (SAMLIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertSamlIdentityProviderConfig(identityProvider);
|
||||
} else if (GoogleIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertGoogleIdentityProviderConfig(identityProvider);
|
||||
} else if (OIDCIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertOidcIdentityProviderConfig(identityProvider);
|
||||
} else if (FacebookIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertFacebookIdentityProviderConfig(identityProvider);
|
||||
} else if (GitHubIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertGitHubIdentityProviderConfig(identityProvider);
|
||||
} else if (TwitterIdentityProviderFactory.PROVIDER_ID.equals(providerId)) {
|
||||
assertTwitterIdentityProviderConfig(identityProvider);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
checkedProviders.remove(providerId);
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(checkedProviders.isEmpty());
|
||||
}
|
||||
|
||||
private void assertGoogleIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
GoogleIdentityProvider googleIdentityProvider = new GoogleIdentityProviderFactory().create(identityProvider);
|
||||
OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-google", config.getId());
|
||||
assertEquals(GoogleIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Google", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(GoogleIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(GoogleIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(GoogleIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
|
||||
}
|
||||
|
||||
private void assertSamlIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
SAMLIdentityProvider samlIdentityProvider = new SAMLIdentityProviderFactory().create(identityProvider);
|
||||
SAMLIdentityProviderConfig config = samlIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-saml-signed-idp", config.getId());
|
||||
assertEquals(SAMLIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("SAML Signed IdP", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("http://localhost:8082/auth/realms/realm-with-saml-identity-provider/protocol/saml", config.getSingleSignOnServiceUrl());
|
||||
assertEquals("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", config.getNameIDPolicyFormat());
|
||||
assertEquals("MIIDdzCCAl+gAwIBAgIEbySuqTANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRAwDgYDVQQDEwdVbmtub3duMB4XDTE1MDEyODIyMTYyMFoXDTE3MTAyNDIyMTYyMFowbDEQMA4GA1UEBhMHVW5rbm93bjEQMA4GA1UECBMHVW5rbm93bjEQMA4GA1UEBxMHVW5rbm93bjEQMA4GA1UEChMHVW5rbm93bjEQMA4GA1UECxMHVW5rbm93bjEQMA4GA1UEAxMHVW5rbm93bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAII/K9NNvXi9IySl7+l2zY/kKrGTtuR4WdCI0xLW/Jn4dLY7v1/HOnV4CC4ecFOzhdNFPtJkmEhP/q62CpmOYOKApXk3tfmm2rwEz9bWprVxgFGKnbrWlz61Z/cjLAlhD3IUj2ZRBquYgSXQPsYfXo1JmSWF5pZ9uh1FVqu9f4wvRqY20ZhUN+39F+1iaBsoqsrbXypCn1HgZkW1/9D9GZug1c3vB4wg1TwZZWRNGtxwoEhdK6dPrNcZ+6PdanVilWrbQFbBjY4wz8/7IMBzssoQ7Usmo8F1Piv0FGfaVeJqBrcAvbiBMpk8pT+27u6p8VyIX6LhGvnxIwM07NByeSUCAwEAAaMhMB8wHQYDVR0OBBYEFFlcNuTYwI9W0tQ224K1gFJlMam0MA0GCSqGSIb3DQEBCwUAA4IBAQB5snl1KWOJALtAjLqD0mLPg1iElmZP82Lq1htLBt3XagwzU9CaeVeCQ7lTp+DXWzPa9nCLhsC3QyrV3/+oqNli8C6NpeqI8FqN2yQW/QMWN1m5jWDbmrWwtQzRUn/rh5KEb5m3zPB+tOC6e/2bV3QeQebxeW7lVMD0tSCviUg1MQf1l2gzuXQo60411YwqrXwk6GMkDOhFDQKDlMchO3oRbQkGbcP8UeiKAXjMeHfzbiBr+cWz8NYZEtxUEDYDjTpKrYCSMJBXpmgVJCZ00BswbksxJwaGqGMPpUKmCV671pf3m8nq3xyiHMDGuGwtbU+GE8kVx85menmp8+964nin", config.getSigningCertificate());
|
||||
assertEquals(true, config.isWantAuthnRequestsSigned());
|
||||
assertEquals(true, config.isForceAuthn());
|
||||
assertEquals(true, config.isPostBindingAuthnRequest());
|
||||
assertEquals(true, config.isPostBindingResponse());
|
||||
assertEquals(true, config.isValidateSignature());
|
||||
}
|
||||
|
||||
private void assertOidcIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
OIDCIdentityProvider googleIdentityProvider = new OIDCIdentityProviderFactory().create(identityProvider);
|
||||
OIDCIdentityProviderConfig config = googleIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-oidc-idp", config.getId());
|
||||
assertEquals(OIDCIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("OIDC IdP", config.getName());
|
||||
assertEquals(false, config.isEnabled());
|
||||
assertEquals(false, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
}
|
||||
|
||||
private void assertFacebookIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
FacebookIdentityProvider facebookIdentityProvider = new FacebookIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = facebookIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-facebook", config.getId());
|
||||
assertEquals(FacebookIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Facebook", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(FacebookIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(FacebookIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(FacebookIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
}
|
||||
|
||||
private void assertGitHubIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
GitHubIdentityProvider gitHubIdentityProvider = new GitHubIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = gitHubIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-github", config.getId());
|
||||
assertEquals(GitHubIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("GitHub", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(false, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
assertEquals(GitHubIdentityProvider.AUTH_URL, config.getAuthorizationUrl());
|
||||
assertEquals(GitHubIdentityProvider.TOKEN_URL, config.getTokenUrl());
|
||||
assertEquals(GitHubIdentityProvider.PROFILE_URL, config.getUserInfoUrl());
|
||||
}
|
||||
|
||||
private void assertTwitterIdentityProviderConfig(IdentityProviderModel identityProvider) {
|
||||
TwitterIdentityProvider twitterIdentityProvider = new TwitterIdentityProviderFactory().create(identityProvider);
|
||||
OAuth2IdentityProviderConfig config = twitterIdentityProvider.getConfig();
|
||||
|
||||
assertEquals("model-twitter", config.getId());
|
||||
assertEquals(TwitterIdentityProviderFactory.PROVIDER_ID, config.getProviderId());
|
||||
assertEquals("Twitter", config.getName());
|
||||
assertEquals(true, config.isEnabled());
|
||||
assertEquals(true, config.isUpdateProfileFirstLogin());
|
||||
assertEquals(false, config.isAuthenticateByDefault());
|
||||
assertEquals(true, config.isStoreToken());
|
||||
assertEquals("clientId", config.getClientId());
|
||||
assertEquals("clientSecret", config.getClientSecret());
|
||||
}
|
||||
|
||||
private RealmModel installTestRealm() throws IOException {
|
||||
RealmRepresentation realmRepresentation = loadJson("broker-test/test-realm-with-broker.json");
|
||||
|
||||
assertNotNull(realmRepresentation);
|
||||
assertEquals("realm-with-broker", realmRepresentation.getRealm());
|
||||
|
||||
RealmModel realmModel = this.realmManager.getRealm("realm-with-broker");
|
||||
|
||||
if (realmModel == null) {
|
||||
realmModel = this.realmManager.importRealm(realmRepresentation);
|
||||
|
||||
commit();
|
||||
|
||||
realmModel = this.realmManager.getRealm(realmModel.getId());
|
||||
|
||||
assertNotNull(realmModel);
|
||||
}
|
||||
|
||||
return realmModel;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue