KEYCLOAK-3499 More fixes for IncludeInUserInfo. Fixing tests and migration

This commit is contained in:
mposolda 2016-10-18 12:43:39 +02:00
parent c3b577de11
commit a7287aad36
24 changed files with 491 additions and 277 deletions

View file

@ -30,6 +30,7 @@ import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0;
import org.keycloak.migration.migrators.MigrateTo2_1_0;
import org.keycloak.migration.migrators.MigrateTo2_2_0;
import org.keycloak.migration.migrators.MigrateTo2_3_0;
import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession;
@ -53,6 +54,7 @@ public class MigrationModelManager {
new MigrateTo2_0_0(),
new MigrateTo2_1_0(),
new MigrateTo2_2_0(),
new MigrateTo2_3_0(),
};
public static void migrate(KeycloakSession session) {

View file

@ -0,0 +1,69 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.migration.migrators;
import java.util.LinkedList;
import java.util.List;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperContainerModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MigrateTo2_3_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("2.3.0");
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
for (ClientModel client : realm.getClients()) {
updateProtocolMappers(client);
}
for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
updateProtocolMappers(clientTemplate);
}
}
}
private void updateProtocolMappers(ProtocolMapperContainerModel client) {
List<ProtocolMapperModel> toUpdate = new LinkedList<>();
for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
if (!mapper.getConfig().containsKey("userinfo.token.claim") && mapper.getConfig().containsKey("id.token.claim")) {
mapper.getConfig().put("userinfo.token.claim", mapper.getConfig().get("id.token.claim"));
toUpdate.add(mapper);
}
}
for (ProtocolMapperModel mapper : toUpdate) {
client.updateProtocolMapper(mapper);
}
}
@Override
public ModelVersion getVersion() {
return VERSION;
}
}

View file

@ -35,7 +35,7 @@ import java.util.Set;
*
* @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a>
*/
abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper {
abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
/**
* Returns the role names extracted from the given {@code roleModels} while recursively traversing "Composite Roles".

View file

@ -44,21 +44,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, AddressMapper.class);
}
public static final String PROVIDER_ID = "oidc-address-mapper";

View file

@ -43,21 +43,7 @@ public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, FullNameMapper.class);
}

View file

@ -45,16 +45,8 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property1.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property1.setType(ProviderConfigProperty.STRING_TYPE);
property1.setDefaultValue("groups");
property1.setHelpText(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_TOOLTIP);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
ProviderConfigProperty property1 = new ProviderConfigProperty();
property1.setName("full.path");
property1.setLabel("Full group path");
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
@ -62,23 +54,7 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
property1.setHelpText("Include full path to group i.e. /top/level1/level2, false will just specify the group name");
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property1.setDefaultValue("true");
property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property1.setDefaultValue("true");
property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property1);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, GroupMembershipMapper.class);
}
public static final String PROVIDER_ID = "oidc-group-membership-mapper";

View file

@ -44,46 +44,17 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
public static final String CLAIM_VALUE = "claim.value";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText("Claim name you want to hard code 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 ProviderConfigProperty();
OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(CLAIM_VALUE);
property.setLabel("Claim value");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText("Value of the claim you want to hard code. 'true' and 'false can be used for boolean values.");
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
List<String> types = new ArrayList(3);
types.add("String");
types.add("long");
types.add("int");
types.add("boolean");
property.setType(ProviderConfigProperty.LIST_TYPE);
property.setOptions(types);
property.setHelpText("JSON type that should be used for the value of the claim. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addJsonTypeConfig(configProperties);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, HardcodedClaim.class);
}
public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";

View file

@ -18,6 +18,7 @@
package org.keycloak.protocol.oidc.mappers;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
@ -162,20 +163,34 @@ public class OIDCAttributeMapperHelper {
}
public static boolean includeInUserInfo(ProtocolMapperModel mappingModel){
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_USERINFO));
String includeInUserInfo = mappingModel.getConfig().get(INCLUDE_IN_USERINFO);
// Backwards compatibility
if (includeInUserInfo == null && includeInIDToken(mappingModel)) {
return true;
}
public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) {
return "true".equals(includeInUserInfo);
}
ProviderConfigProperty property;
property = new ProviderConfigProperty();
public static void addAttributeConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
addTokenClaimNameConfig(configProperties);
addJsonTypeConfig(configProperties);
addIncludeInTokensConfig(configProperties, protocolMapperClass);
}
public static void addTokenClaimNameConfig(List<ProviderConfigProperty> configProperties) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(TOKEN_CLAIM_NAME);
property.setLabel(TOKEN_CLAIM_NAME_LABEL);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText(TOKEN_CLAIM_NAME_TOOLTIP);
configProperties.add(property);
}
property = new ProviderConfigProperty();
public static void addJsonTypeConfig(List<ProviderConfigProperty> configProperties) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(JSON_TYPE);
property.setLabel(JSON_TYPE);
List<String> types = new ArrayList(3);
@ -187,24 +202,31 @@ public class OIDCAttributeMapperHelper {
property.setOptions(types);
property.setHelpText(JSON_TYPE_TOOLTIP);
configProperties.add(property);
}
property = new ProviderConfigProperty();
public static void addIncludeInTokensConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
if (OIDCIDTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_ID_TOKEN);
property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
}
property = new ProviderConfigProperty();
if (OIDCAccessTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
}
property = new ProviderConfigProperty();
if (UserInfoTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_USERINFO);
property.setLabel(INCLUDE_IN_USERINFO_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
@ -213,3 +235,4 @@ public class OIDCAttributeMapperHelper {
configProperties.add(property);
}
}
}

View file

@ -51,7 +51,7 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserAttributeMapper.class);
property = new ProviderConfigProperty();
property.setName(ProtocolMapperUtils.MULTIVALUED);

View file

@ -47,7 +47,7 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
clientId.setName(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID);
clientId.setLabel(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_LABEL);
clientId.setHelpText(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_HELP_TEXT);
clientId.setType(ProviderConfigProperty.STRING_TYPE);
clientId.setType(ProviderConfigProperty.CLIENT_LIST_TYPE);
CONFIG_PROPERTIES.add(clientId);
ProviderConfigProperty clientRolePrefix = new ProviderConfigProperty();
@ -57,7 +57,7 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
clientRolePrefix.setType(ProviderConfigProperty.STRING_TYPE);
CONFIG_PROPERTIES.add(clientRolePrefix);
OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES);
OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES, UserClientRoleMappingMapper.class);
}
public List<ProviderConfigProperty> getConfigProperties() {
@ -100,4 +100,21 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, clientRoleNames);
}
}
public static ProtocolMapperModel create(String clientId, String clientRolePrefix,
String name,
String tokenClaimName,
boolean accessToken, boolean idToken) {
ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, "foo",
tokenClaimName, "String",
true, name,
accessToken, idToken,
PROVIDER_ID);
mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID, clientId);
mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX, clientRolePrefix);
return mapper;
}
}

View file

@ -38,7 +38,7 @@ import java.util.List;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
@ -49,7 +49,7 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserPropertyMapper.class);
}
public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";

View file

@ -21,11 +21,14 @@ import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@ -48,7 +51,7 @@ public class UserRealmRoleMappingMapper extends AbstractUserRoleMappingMapper {
realmRolePrefix.setType(ProviderConfigProperty.STRING_TYPE);
CONFIG_PROPERTIES.add(realmRolePrefix);
OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES);
OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES, UserRealmRoleMappingMapper.class);
}
public List<ProviderConfigProperty> getConfigProperties() {
@ -80,8 +83,23 @@ public class UserRealmRoleMappingMapper extends AbstractUserRoleMappingMapper {
UserModel user = userSession.getUser();
String rolePrefix = mappingModel.getConfig().get(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX);
Set<String> realmRoleNames = flattenRoleModelToRoleNames(user.getRoleMappings(), rolePrefix);
Set<String> realmRoleNames = flattenRoleModelToRoleNames(user.getRealmRoleMappings(), rolePrefix);
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, realmRoleNames);
}
public static ProtocolMapperModel create(String realmRolePrefix,
String name,
String tokenClaimName, boolean accessToken, boolean idToken) {
ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, "foo",
tokenClaimName, "String",
true, name,
accessToken, idToken,
PROVIDER_ID);
mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX, realmRolePrefix);
return mapper;
}
}

View file

@ -49,7 +49,7 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements
property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserSessionNoteMapper.class);
}
public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";

View file

@ -49,7 +49,7 @@ public class UserInfoClientUtil {
return client.target(userInfoUri);
}
public static void testSuccessfulUserInfoResponse(Response response, String expectedUsername, String expectedEmail) {
public static UserInfo testSuccessfulUserInfoResponse(Response response, String expectedUsername, String expectedEmail) {
Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JSON);
@ -61,6 +61,7 @@ public class UserInfoClientUtil {
Assert.assertNotNull(userInfo.getSubject());
Assert.assertEquals(expectedEmail, userInfo.getEmail());
Assert.assertEquals(expectedUsername, userInfo.getPreferredUsername());
return userInfo;
}
}

View file

@ -27,6 +27,7 @@ import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.HttpErrorException;
import org.keycloak.protocol.oidc.mappers.SHA256PairwiseSubMapper;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.UserInfo;
import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
@ -38,7 +39,9 @@ import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
import org.keycloak.testsuite.util.ClientManager;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.UserInfoClientUtil;
import javax.ws.rs.client.Client;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Collections;
@ -323,5 +326,17 @@ public class OIDCPairwiseClientRegistrationTest extends AbstractClientRegistrati
// Assert pairwise client has different subject like userId
String pairwiseUserId = accessToken.getSubject();
Assert.assertNotEquals(pairwiseUserId, user.getId());
// Send request to userInfo endpoint
Client jaxrsClient = javax.ws.rs.client.ClientBuilder.newClient();
try {
// Check that userInfo contains pairwise subjectId as well
Response userInfoResponse = UserInfoClientUtil.executeUserInfoRequest_getMethod(jaxrsClient, accessTokenResponse.getAccessToken());
UserInfo userInfo = UserInfoClientUtil.testSuccessfulUserInfoResponse(userInfoResponse, "test-user", "test-user@localhost");
String userInfoSubId = userInfo.getSubject();
Assert.assertEquals(pairwiseUserId, userInfoSubId);
} finally {
jaxrsClient.close();
}
}
}

View file

@ -673,138 +673,6 @@ public class AccessTokenTest extends AbstractKeycloakTest {
}
@Test
public void testTokenMapping() throws Exception {
Client client = javax.ws.rs.client.ClientBuilder.newClient();
UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
WebTarget grantTarget = client.target(grantUri);
{
UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
UserRepresentation user = userResource.toRepresentation();
user.singleAttribute("street", "5 Yawkey Way");
user.singleAttribute("locality", "Boston");
user.singleAttribute("region", "MA");
user.singleAttribute("postal_code", "02115");
user.singleAttribute("country", "USA");
user.singleAttribute("phone", "617-777-6666");
List<String> departments = Arrays.asList("finance", "development");
user.getAttributes().put("departments", departments);
userResource.update(user);
ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
app.getProtocolMappers().createMapper(mapper);
ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
app.getProtocolMappers().createMapper(hard);
app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
app.getProtocolMappers().createMapper(createHardcodedRole("hard-app", "app.hardcoded"));
app.getProtocolMappers().createMapper(createRoleNameMapper("rename-app-role", "test-app.customer-user", "realm-user"));
}
{
Response response = executeGrantAccessTokenRequest(grantTarget);
assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
IDToken idToken = getIdToken(tokenResponse);
assertNotNull(idToken.getAddress());
assertEquals(idToken.getName(), "Tom Brady");
assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
assertEquals(idToken.getAddress().getLocality(), "Boston");
assertEquals(idToken.getAddress().getRegion(), "MA");
assertEquals(idToken.getAddress().getPostalCode(), "02115");
assertEquals(idToken.getAddress().getCountry(), "USA");
assertNotNull(idToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
assertEquals("coded", idToken.getOtherClaims().get("hard"));
Map nested = (Map) idToken.getOtherClaims().get("nested");
assertEquals("coded-nested", nested.get("hard"));
nested = (Map) idToken.getOtherClaims().get("home");
assertEquals("617-777-6666", nested.get("phone"));
List<String> departments = (List<String>) idToken.getOtherClaims().get("department");
assertEquals(2, departments.size());
assertTrue(departments.contains("finance") && departments.contains("development"));
AccessToken accessToken = getAccessToken(tokenResponse);
assertEquals(accessToken.getName(), "Tom Brady");
assertNotNull(accessToken.getAddress());
assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
assertEquals(accessToken.getAddress().getLocality(), "Boston");
assertEquals(accessToken.getAddress().getRegion(), "MA");
assertEquals(accessToken.getAddress().getPostalCode(), "02115");
assertEquals(accessToken.getAddress().getCountry(), "USA");
assertNotNull(accessToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
assertEquals("coded", accessToken.getOtherClaims().get("hard"));
nested = (Map) accessToken.getOtherClaims().get("nested");
assertEquals("coded-nested", nested.get("hard"));
nested = (Map) accessToken.getOtherClaims().get("home");
assertEquals("617-777-6666", nested.get("phone"));
departments = (List<String>) idToken.getOtherClaims().get("department");
assertEquals(2, departments.size());
assertTrue(departments.contains("finance") && departments.contains("development"));
assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
response.close();
}
// undo mappers
{
ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRepresentation = app.toRepresentation();
for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
if (model.getName().equals("address")
|| model.getName().equals("hard")
|| model.getName().equals("hard-nested")
|| model.getName().equals("custom phone")
|| model.getName().equals("departments")
|| model.getName().equals("nested phone")
|| model.getName().equals("rename-app-role")
|| model.getName().equals("hard-realm")
|| model.getName().equals("hard-app")
) {
app.getProtocolMappers().delete(model.getId());
}
}
}
events.clear();
{
Response response = executeGrantAccessTokenRequest(grantTarget);
assertEquals(200, response.getStatus());
org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
IDToken idToken = getIdToken(tokenResponse);
assertNull(idToken.getAddress());
assertNull(idToken.getOtherClaims().get("home_phone"));
assertNull(idToken.getOtherClaims().get("hard"));
assertNull(idToken.getOtherClaims().get("nested"));
assertNull(idToken.getOtherClaims().get("department"));
response.close();
}
events.clear();
client.close();
}
@Test
public void testClientTemplate() throws Exception {
RealmResource realm = adminClient.realm("test");

View file

@ -0,0 +1,244 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.testsuite.oauth;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ProtocolMappersResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.util.ClientManager;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.ProtocolMapperUtil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
import static org.keycloak.testsuite.admin.ApiUtil.findClientResourceByClientId;
import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsernameId;
import static org.keycloak.testsuite.util.ProtocolMapperUtil.createAddressMapper;
import static org.keycloak.testsuite.util.ProtocolMapperUtil.createClaimMapper;
import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedClaim;
import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedRole;
import static org.keycloak.testsuite.util.ProtocolMapperUtil.createRoleNameMapper;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
@Rule
public AssertEvents events = new AssertEvents(this);
@Override
public void beforeAbstractKeycloakTest() throws Exception {
super.beforeAbstractKeycloakTest();
}
@Before
public void clientConfiguration() {
ClientManager.realm(adminClient.realm("test")).clientId("test-app").directAccessGrant(true);
/*
* Configure the default client ID. Seems like OAuthClient is keeping the state of clientID
* For example: If some test case configure oauth.clientId("sample-public-client"), other tests
* will faile and the clientID will always be "sample-public-client
* @see AccessTokenTest#testAuthorizationNegotiateHeaderIgnored()
*/
oauth.clientId("test-app");
}
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
testRealms.add(realm);
}
@Test
public void testTokenMapping() throws Exception {
{
UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
UserRepresentation user = userResource.toRepresentation();
user.singleAttribute("street", "5 Yawkey Way");
user.singleAttribute("locality", "Boston");
user.singleAttribute("region", "MA");
user.singleAttribute("postal_code", "02115");
user.singleAttribute("country", "USA");
user.singleAttribute("phone", "617-777-6666");
List<String> departments = Arrays.asList("finance", "development");
user.getAttributes().put("departments", departments);
userResource.update(user);
ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
app.getProtocolMappers().createMapper(mapper);
ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
app.getProtocolMappers().createMapper(hard);
app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
app.getProtocolMappers().createMapper(createHardcodedRole("hard-app", "app.hardcoded"));
app.getProtocolMappers().createMapper(createRoleNameMapper("rename-app-role", "test-app.customer-user", "realm-user"));
}
{
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
assertNotNull(idToken.getAddress());
assertEquals(idToken.getName(), "Tom Brady");
assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
assertEquals(idToken.getAddress().getLocality(), "Boston");
assertEquals(idToken.getAddress().getRegion(), "MA");
assertEquals(idToken.getAddress().getPostalCode(), "02115");
assertEquals(idToken.getAddress().getCountry(), "USA");
assertNotNull(idToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
assertEquals("coded", idToken.getOtherClaims().get("hard"));
Map nested = (Map) idToken.getOtherClaims().get("nested");
assertEquals("coded-nested", nested.get("hard"));
nested = (Map) idToken.getOtherClaims().get("home");
assertEquals("617-777-6666", nested.get("phone"));
List<String> departments = (List<String>) idToken.getOtherClaims().get("department");
assertEquals(2, departments.size());
assertTrue(departments.contains("finance") && departments.contains("development"));
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
assertEquals(accessToken.getName(), "Tom Brady");
assertNotNull(accessToken.getAddress());
assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
assertEquals(accessToken.getAddress().getLocality(), "Boston");
assertEquals(accessToken.getAddress().getRegion(), "MA");
assertEquals(accessToken.getAddress().getPostalCode(), "02115");
assertEquals(accessToken.getAddress().getCountry(), "USA");
assertNotNull(accessToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
assertEquals("coded", accessToken.getOtherClaims().get("hard"));
nested = (Map) accessToken.getOtherClaims().get("nested");
assertEquals("coded-nested", nested.get("hard"));
nested = (Map) accessToken.getOtherClaims().get("home");
assertEquals("617-777-6666", nested.get("phone"));
departments = (List<String>) idToken.getOtherClaims().get("department");
assertEquals(2, departments.size());
assertTrue(departments.contains("finance") && departments.contains("development"));
assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
}
// undo mappers
{
ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRepresentation = app.toRepresentation();
for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
if (model.getName().equals("address")
|| model.getName().equals("hard")
|| model.getName().equals("hard-nested")
|| model.getName().equals("custom phone")
|| model.getName().equals("departments")
|| model.getName().equals("nested phone")
|| model.getName().equals("rename-app-role")
|| model.getName().equals("hard-realm")
|| model.getName().equals("hard-app")
) {
app.getProtocolMappers().delete(model.getId());
}
}
}
events.clear();
{
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
assertNull(idToken.getAddress());
assertNull(idToken.getOtherClaims().get("home_phone"));
assertNull(idToken.getOtherClaims().get("hard"));
assertNull(idToken.getOtherClaims().get("nested"));
assertNull(idToken.getOtherClaims().get("department"));
}
events.clear();
}
@Test
public void testUserRoleToAttributeMappers() throws Exception {
// Add mapper for realm roles
ProtocolMapperRepresentation realmMapper = ProtocolMapperUtil.createUserRealmRoleMappingMapper("pref.", "Realm roles mapper", "roles-custom.realm", true, true);
ProtocolMapperRepresentation clientMapper = ProtocolMapperUtil.createUserClientRoleMappingMapper("test-app", null, "Client roles mapper", "roles-custom.test-app", true, true);
ProtocolMappersResource protocolMappers = ApiUtil.findClientResourceByClientId(adminClient.realm("test"), "test-app").getProtocolMappers();
protocolMappers.createMapper(Arrays.asList(realmMapper, clientMapper));
// Login user
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
// Verify attribute is filled
Map<String, Object> roleMappings = (Map<String, Object>)idToken.getOtherClaims().get("roles-custom");
Assert.assertEquals(2, roleMappings.size());
String realmRoleMappings = (String) roleMappings.get("realm");
String testAppMappings = (String) roleMappings.get("test-app");
Assert.assertTrue(realmRoleMappings.contains("pref.user"));
Assert.assertEquals("[customer-user]", testAppMappings);
}
private ProtocolMapperRepresentation makeMapper(String name, String mapperType, Map<String, String> config) {
ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
rep.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
rep.setName(name);
rep.setProtocolMapper(mapperType);
rep.setConfig(config);
rep.setConsentRequired(true);
rep.setConsentText("Test Consent Text");
return rep;
}
}

View file

@ -6,6 +6,8 @@ import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
import org.keycloak.protocol.oidc.mappers.HardcodedRole;
import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
import org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper;
import org.keycloak.protocol.oidc.mappers.UserRealmRoleMappingMapper;
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
@ -103,4 +105,22 @@ public class ProtocolMapperUtil {
consentRequired, consentText,
accessToken, idToken));
}
public static ProtocolMapperRepresentation createUserRealmRoleMappingMapper(String realmRolePrefix,
String name,
String tokenClaimName,
boolean accessToken, boolean idToken) {
return ModelToRepresentation.toRepresentation(UserRealmRoleMappingMapper.create(realmRolePrefix, name, tokenClaimName, accessToken, idToken));
}
public static ProtocolMapperRepresentation createUserClientRoleMappingMapper(String clientId, String clientRolePrefix,
String name,
String tokenClaimName,
boolean accessToken, boolean idToken) {
return ModelToRepresentation.toRepresentation(UserClientRoleMappingMapper.create(clientId, clientRolePrefix, name, tokenClaimName, accessToken, idToken));
}
}

View file

@ -242,7 +242,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
* Test for KEYCLOAK-1053 - verify email action is not performed if email is not provided, login is normal, but action stays in set to be performed later
*/
@Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() throws Exception {
RealmModel realm = getRealm();
realm.setVerifyEmail(true);
setUpdateProfileFirstLogin(realm, IdentityProviderRepresentation.UPFLM_OFF);

View file

@ -151,7 +151,7 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractKeycloakIdentityP
}
@Test
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() throws Exception {
super.testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled();
}

View file

@ -26,8 +26,8 @@
"claim.name": "mobile",
"Claim JSON Type": "String",
"access.token.claim": "true",
"id.token.claim": "true"
"id.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
@ -40,8 +40,8 @@
"claim.name": "preferred_username",
"Claim JSON Type": "String",
"access.token.claim": "true",
"id.token.claim": "true"
"id.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
@ -54,8 +54,8 @@
"claim.name": "email",
"Claim JSON Type": "String",
"access.token.claim": "true",
"id.token.claim": "true"
"id.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
@ -68,8 +68,8 @@
"claim.name": "given_name",
"Claim JSON Type": "String",
"access.token.claim": "true",
"id.token.claim": "true"
"id.token.claim": "true",
"userinfo.token.claim": "true"
}
},
{
@ -83,7 +83,6 @@
"Claim JSON Type": "String",
"access.token.claim": "true",
"id.token.claim": "true"
}
},
{
@ -93,8 +92,8 @@
"consentRequired": false,
"config": {
"access.token.claim": "true",
"id.token.claim": "true"
"id.token.claim": "true",
"userinfo.token.claim": "true"
}
}

View file

@ -953,6 +953,9 @@ module.config([ '$routeProvider', function($routeProvider) {
},
mapper : function(ClientProtocolMapperLoader) {
return ClientProtocolMapperLoader();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
@ -969,6 +972,9 @@ module.config([ '$routeProvider', function($routeProvider) {
},
client : function(ClientLoader) {
return ClientLoader();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
controller : 'ClientProtocolMapperCreateCtrl'
@ -1017,6 +1023,9 @@ module.config([ '$routeProvider', function($routeProvider) {
},
mapper : function(ClientTemplateProtocolMapperLoader) {
return ClientTemplateProtocolMapperLoader();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
@ -1033,6 +1042,9 @@ module.config([ '$routeProvider', function($routeProvider) {
},
template : function(ClientTemplateLoader) {
return ClientTemplateLoader();
},
clients : function(ClientListLoader) {
return ClientListLoader();
}
},
controller : 'ClientTemplateProtocolMapperCreateCtrl'

View file

@ -1705,8 +1705,10 @@ module.controller('ClientProtocolMapperListCtrl', function($scope, realm, client
updateMappers();
});
module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, clients, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
$scope.realm = realm;
$scope.clients = clients;
/*
$scope.client = client;
$scope.create = false;
@ -1786,8 +1788,9 @@ module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo
});
module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, ClientProtocolMapper, Notifications, Dialog, $location) {
module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, clients, ClientProtocolMapper, Notifications, Dialog, $location) {
$scope.realm = realm;
$scope.clients = clients;
if (client.protocol == null) {
client.protocol = 'openid-connect';
@ -2001,8 +2004,10 @@ module.controller('ClientTemplateProtocolMapperListCtrl', function($scope, realm
updateMappers();
});
module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, serverInfo, template, mapper, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, serverInfo, template, mapper, clients, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
$scope.realm = realm;
$scope.clients = clients;
if (template.protocol == null) {
template.protocol = 'openid-connect';
}
@ -2068,8 +2073,10 @@ module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, se
});
module.controller('ClientTemplateProtocolMapperCreateCtrl', function($scope, realm, serverInfo, template, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
module.controller('ClientTemplateProtocolMapperCreateCtrl', function($scope, realm, serverInfo, template, clients, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
$scope.realm = realm;
$scope.clients = clients;
if (template.protocol == null) {
template.protocol = 'openid-connect';
}

View file

@ -60,7 +60,7 @@
</div>
<kc-tooltip>{{model.mapperType.helpText}}</kc-tooltip>
</div>
<kc-provider-config config="model.mapper.config" properties="model.mapperType.properties" realm="model.realm"></kc-provider-config>
<kc-provider-config config="model.mapper.config" properties="model.mapperType.properties" realm="model.realm" clients="clients"></kc-provider-config>
</fieldset>
<div class="form-group">