KEYCLOAK-6577 KEYCLOAK-5609 Support dot in claim names by escaping with backslash
This commit is contained in:
parent
c8bc0d6d7b
commit
b43392bac8
13 changed files with 189 additions and 18 deletions
|
@ -173,6 +173,11 @@
|
|||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-all</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.icegreen</groupId>
|
||||
<artifactId>greenmail</artifactId>
|
||||
|
|
|
@ -23,10 +23,14 @@ import org.keycloak.broker.oidc.OIDCIdentityProvider;
|
|||
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
|
||||
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||
import org.keycloak.models.IdentityProviderMapperModel;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.representations.JsonWebToken;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -37,13 +41,16 @@ public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper
|
|||
public static final String CLAIM_VALUE = "claim.value";
|
||||
|
||||
public static Object getClaimValue(JsonWebToken token, String claim) {
|
||||
String[] split = claim.split("\\.");
|
||||
List<String> split = OIDCAttributeMapperHelper.splitClaimPath(claim);
|
||||
Map<String, Object> jsonObject = token.getOtherClaims();
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (i == split.length - 1) {
|
||||
return jsonObject.get(split[i]);
|
||||
final int length = split.size();
|
||||
int i = 0;
|
||||
for (String component : split) {
|
||||
i++;
|
||||
if (i == length) {
|
||||
return jsonObject.get(component);
|
||||
} else {
|
||||
Object val = jsonObject.get(split[i]);
|
||||
Object val = jsonObject.get(component);
|
||||
if (!(val instanceof Map)) return null;
|
||||
jsonObject = (Map<String, Object>)val;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class ClaimToRoleMapper extends AbstractClaimMapper {
|
|||
property1 = new ProviderConfigProperty();
|
||||
property1.setName(CLAIM);
|
||||
property1.setLabel("Claim");
|
||||
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
|
||||
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'. To use dot (.) literally, escape it with backslash (\\.)");
|
||||
property1.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(property1);
|
||||
property1 = new ProviderConfigProperty();
|
||||
|
|
|
@ -56,7 +56,7 @@ public class UserAttributeMapper extends AbstractClaimMapper {
|
|||
property1 = new ProviderConfigProperty();
|
||||
property1.setName(CLAIM);
|
||||
property1.setLabel("Claim");
|
||||
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
|
||||
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'. To use dot (.) literally, escape it with backslash (\\.)");
|
||||
property1.setType(ProviderConfigProperty.STRING_TYPE);
|
||||
configProperties.add(property1);
|
||||
property = new ProviderConfigProperty();
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.keycloak.services.ServicesLogger;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -143,6 +145,28 @@ public class OIDCAttributeMapperHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
// A character in a claim component is either a literal character escaped by a backslash (\., \\, \_, \q, etc.)
|
||||
// or any character other than backslash (escaping) and dot (claim component separator)
|
||||
private static final Pattern CLAIM_COMPONENT = Pattern.compile("^((\\\\.|[^\\\\.])+?)\\.");
|
||||
|
||||
private static final Pattern BACKSLASHED_CHARACTER = Pattern.compile("\\\\(.)");
|
||||
|
||||
public static List<String> splitClaimPath(String claimPath) {
|
||||
final LinkedList<String> claimComponents = new LinkedList<>();
|
||||
Matcher m = CLAIM_COMPONENT.matcher(claimPath);
|
||||
int start = 0;
|
||||
while (m.find()) {
|
||||
claimComponents.add(BACKSLASHED_CHARACTER.matcher(m.group(1)).replaceAll("$1"));
|
||||
start = m.end();
|
||||
// This is necessary to match the start of region as the start of string as determined by ^
|
||||
m.region(start, claimPath.length());
|
||||
}
|
||||
if (claimPath.length() > start) {
|
||||
claimComponents.add(BACKSLASHED_CHARACTER.matcher(claimPath.substring(start)).replaceAll("$1"));
|
||||
}
|
||||
return claimComponents;
|
||||
}
|
||||
|
||||
public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
|
||||
attributeValue = mapAttributeValue(mappingModel, attributeValue);
|
||||
if (attributeValue == null) return;
|
||||
|
@ -151,17 +175,20 @@ public class OIDCAttributeMapperHelper {
|
|||
if (protocolClaim == null) {
|
||||
return;
|
||||
}
|
||||
String[] split = protocolClaim.split("\\.");
|
||||
List<String> split = splitClaimPath(protocolClaim);
|
||||
final int length = split.size();
|
||||
int i = 0;
|
||||
Map<String, Object> jsonObject = token.getOtherClaims();
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (i == split.length - 1) {
|
||||
jsonObject.put(split[i], attributeValue);
|
||||
for (String component : split) {
|
||||
i++;
|
||||
if (i == length) {
|
||||
jsonObject.put(component, attributeValue);
|
||||
} else {
|
||||
Map<String, Object> nested = (Map<String, Object>)jsonObject.get(split[i]);
|
||||
Map<String, Object> nested = (Map<String, Object>)jsonObject.get(component);
|
||||
|
||||
if (nested == null) {
|
||||
nested = new HashMap<String, Object>();
|
||||
jsonObject.put(split[i], nested);
|
||||
jsonObject.put(component, nested);
|
||||
}
|
||||
|
||||
jsonObject = nested;
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2018 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.protocol.oidc.mappers;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class OIDCAttributeMapperHelperTest {
|
||||
|
||||
@Test
|
||||
public void testSplitClaimPath() {
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath(""), Matchers.empty());
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("a"), Matchers.contains("a"));
|
||||
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("a.b"), Matchers.contains("a", "b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("a\\.b"), Matchers.contains("a.b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("a\\\\.b"), Matchers.contains("a\\", "b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("a\\\\\\.b"), Matchers.contains("a\\.b"));
|
||||
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("c.a\\\\.b"), Matchers.contains("c", "a\\", "b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("c.a\\\\\\.b"), Matchers.contains("c", "a\\.b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("c\\\\\\.b.a\\\\\\.b"), Matchers.contains("c\\.b", "a\\.b"));
|
||||
assertThat(OIDCAttributeMapperHelper.splitClaimPath("c\\h\\.b.a\\\\\\.b"), Matchers.contains("ch.b", "a\\.b"));
|
||||
}
|
||||
}
|
|
@ -37,6 +37,8 @@ public abstract class AbstractUserAttributeMapperTest extends AbstractBaseBroker
|
|||
|
||||
private static final Set<String> PROTECTED_NAMES = ImmutableSet.<String>builder().add("email").add("lastName").add("firstName").build();
|
||||
private static final Map<String, String> ATTRIBUTE_NAME_TRANSLATION = ImmutableMap.<String, String>builder()
|
||||
.put("dotted.email", "dotted.email")
|
||||
.put("nested.email", "nested.email")
|
||||
.put(ATTRIBUTE_TO_MAP_FRIENDLY_NAME, MAPPED_ATTRIBUTE_FRIENDLY_NAME)
|
||||
.put(ATTRIBUTE_TO_MAP_NAME, MAPPED_ATTRIBUTE_NAME)
|
||||
.build();
|
||||
|
@ -198,9 +200,13 @@ public abstract class AbstractUserAttributeMapperTest extends AbstractBaseBroker
|
|||
public void testBasicMappingEmail() {
|
||||
testValueMapping(ImmutableMap.<String, List<String>>builder()
|
||||
.put("email", ImmutableList.<String>builder().add(bc.getUserEmail()).build())
|
||||
.put("nested.email", ImmutableList.<String>builder().add(bc.getUserEmail()).build())
|
||||
.put("dotted.email", ImmutableList.<String>builder().add(bc.getUserEmail()).build())
|
||||
.build(),
|
||||
ImmutableMap.<String, List<String>>builder()
|
||||
.put("email", ImmutableList.<String>builder().add("other_email@redhat.com").build())
|
||||
.put("nested.email", ImmutableList.<String>builder().add("other_email@redhat.com").build())
|
||||
.put("dotted.email", ImmutableList.<String>builder().add("other_email@redhat.com").build())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,32 @@ public class KcOidcBrokerConfiguration implements BrokerConfiguration {
|
|||
emailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
emailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
|
||||
ProtocolMapperRepresentation nestedAttrMapper = new ProtocolMapperRepresentation();
|
||||
nestedAttrMapper.setName("attribute - nested claim");
|
||||
nestedAttrMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
nestedAttrMapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
|
||||
Map<String, String> nestedEmailMapperConfig = nestedAttrMapper.getConfig();
|
||||
nestedEmailMapperConfig.put(ProtocolMapperUtils.USER_ATTRIBUTE, "nested.email");
|
||||
nestedEmailMapperConfig.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "nested.email");
|
||||
nestedEmailMapperConfig.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
nestedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
nestedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
nestedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
|
||||
ProtocolMapperRepresentation dottedAttrMapper = new ProtocolMapperRepresentation();
|
||||
dottedAttrMapper.setName("attribute - claim with dot in name");
|
||||
dottedAttrMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
dottedAttrMapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
|
||||
Map<String, String> dottedEmailMapperConfig = dottedAttrMapper.getConfig();
|
||||
dottedEmailMapperConfig.put(ProtocolMapperUtils.USER_ATTRIBUTE, "dotted.email");
|
||||
dottedEmailMapperConfig.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "dotted\\.email");
|
||||
dottedEmailMapperConfig.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
dottedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
dottedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
dottedEmailMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
|
||||
ProtocolMapperRepresentation userAttrMapper = new ProtocolMapperRepresentation();
|
||||
userAttrMapper.setName("attribute - name");
|
||||
userAttrMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
|
@ -88,7 +114,7 @@ public class KcOidcBrokerConfiguration implements BrokerConfiguration {
|
|||
userAttrMapperConfig.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
userAttrMapperConfig.put(ProtocolMapperUtils.MULTIVALUED, "true");
|
||||
|
||||
client.setProtocolMappers(Arrays.asList(emailMapper, userAttrMapper));
|
||||
client.setProtocolMappers(Arrays.asList(emailMapper, userAttrMapper, nestedAttrMapper, dottedAttrMapper));
|
||||
|
||||
return Collections.singletonList(client);
|
||||
}
|
||||
|
|
|
@ -97,6 +97,26 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
|
|||
emailMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, "urn:oasis:names:tc:SAML:2.0:attrname-format:uri");
|
||||
emailMapperConfig.put(AttributeStatementHelper.FRIENDLY_NAME, "email");
|
||||
|
||||
ProtocolMapperRepresentation dottedAttrMapper = new ProtocolMapperRepresentation();
|
||||
dottedAttrMapper.setName("email - dotted");
|
||||
dottedAttrMapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
dottedAttrMapper.setProtocolMapper(UserAttributeStatementMapper.PROVIDER_ID);
|
||||
|
||||
Map<String, String> dottedEmailMapperConfig = dottedAttrMapper.getConfig();
|
||||
dottedEmailMapperConfig.put(ProtocolMapperUtils.USER_ATTRIBUTE, "dotted.email");
|
||||
dottedEmailMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "dotted.email");
|
||||
dottedEmailMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, "urn:oasis:names:tc:SAML:2.0:attrname-format:uri");
|
||||
|
||||
ProtocolMapperRepresentation nestedAttrMapper = new ProtocolMapperRepresentation();
|
||||
nestedAttrMapper.setName("email - nested");
|
||||
nestedAttrMapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
nestedAttrMapper.setProtocolMapper(UserAttributeStatementMapper.PROVIDER_ID);
|
||||
|
||||
Map<String, String> nestedEmailMapperConfig = nestedAttrMapper.getConfig();
|
||||
nestedEmailMapperConfig.put(ProtocolMapperUtils.USER_ATTRIBUTE, "nested.email");
|
||||
nestedEmailMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "nested.email");
|
||||
nestedEmailMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, "urn:oasis:names:tc:SAML:2.0:attrname-format:uri");
|
||||
|
||||
ProtocolMapperRepresentation userAttrMapper = new ProtocolMapperRepresentation();
|
||||
userAttrMapper.setName("attribute - name");
|
||||
userAttrMapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
|
@ -119,7 +139,7 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
|
|||
userFriendlyAttrMapperConfig.put(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT, AttributeStatementHelper.BASIC);
|
||||
userFriendlyAttrMapperConfig.put(AttributeStatementHelper.FRIENDLY_NAME, AbstractUserAttributeMapperTest.ATTRIBUTE_TO_MAP_FRIENDLY_NAME);
|
||||
|
||||
client.setProtocolMappers(Arrays.asList(emailMapper, userAttrMapper, userFriendlyAttrMapper));
|
||||
client.setProtocolMappers(Arrays.asList(emailMapper, dottedAttrMapper, nestedAttrMapper, userAttrMapper, userFriendlyAttrMapper));
|
||||
|
||||
return client;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,23 @@ public class OidcUserAttributeMapperTest extends AbstractUserAttributeMapperTest
|
|||
.put(UserAttributeMapper.USER_ATTRIBUTE, "email")
|
||||
.build());
|
||||
|
||||
return Lists.newArrayList(attrMapper1, emailAttrMapper);
|
||||
IdentityProviderMapperRepresentation nestedEmailAttrMapper = new IdentityProviderMapperRepresentation();
|
||||
nestedEmailAttrMapper.setName("nested-attribute-mapper-email");
|
||||
nestedEmailAttrMapper.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
nestedEmailAttrMapper.setConfig(ImmutableMap.<String,String>builder()
|
||||
.put(UserAttributeMapper.CLAIM, "nested.email")
|
||||
.put(UserAttributeMapper.USER_ATTRIBUTE, "nested.email")
|
||||
.build());
|
||||
|
||||
IdentityProviderMapperRepresentation dottedEmailAttrMapper = new IdentityProviderMapperRepresentation();
|
||||
dottedEmailAttrMapper.setName("dotted-attribute-mapper-email");
|
||||
dottedEmailAttrMapper.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
dottedEmailAttrMapper.setConfig(ImmutableMap.<String,String>builder()
|
||||
.put(UserAttributeMapper.CLAIM, "dotted\\.email")
|
||||
.put(UserAttributeMapper.USER_ATTRIBUTE, "dotted.email")
|
||||
.build());
|
||||
|
||||
return Lists.newArrayList(attrMapper1, emailAttrMapper, nestedEmailAttrMapper, dottedEmailAttrMapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,22 @@ public class SamlUserAttributeMapperTest extends AbstractUserAttributeMapperTest
|
|||
.put(UserAttributeMapper.USER_ATTRIBUTE, "email")
|
||||
.build());
|
||||
|
||||
IdentityProviderMapperRepresentation attrMapperNestedEmail = new IdentityProviderMapperRepresentation();
|
||||
attrMapperNestedEmail.setName("nested-attribute-mapper-email");
|
||||
attrMapperNestedEmail.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
attrMapperNestedEmail.setConfig(ImmutableMap.<String,String>builder()
|
||||
.put(UserAttributeMapper.ATTRIBUTE_NAME, "nested.email")
|
||||
.put(UserAttributeMapper.USER_ATTRIBUTE, "nested.email")
|
||||
.build());
|
||||
|
||||
IdentityProviderMapperRepresentation attrMapperDottedEmail = new IdentityProviderMapperRepresentation();
|
||||
attrMapperDottedEmail.setName("dotted-attribute-mapper-email");
|
||||
attrMapperDottedEmail.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
attrMapperDottedEmail.setConfig(ImmutableMap.<String,String>builder()
|
||||
.put(UserAttributeMapper.ATTRIBUTE_NAME, "dotted.email")
|
||||
.put(UserAttributeMapper.USER_ATTRIBUTE, "dotted.email")
|
||||
.build());
|
||||
|
||||
IdentityProviderMapperRepresentation attrMapper1 = new IdentityProviderMapperRepresentation();
|
||||
attrMapper1.setName("attribute-mapper");
|
||||
attrMapper1.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
|
@ -40,7 +56,7 @@ public class SamlUserAttributeMapperTest extends AbstractUserAttributeMapperTest
|
|||
.put(UserAttributeMapper.USER_ATTRIBUTE, MAPPED_ATTRIBUTE_FRIENDLY_NAME)
|
||||
.build());
|
||||
|
||||
return Lists.newArrayList(attrMapperEmail, attrMapper1, attrMapper2);
|
||||
return Lists.newArrayList(attrMapperEmail, attrMapper1, attrMapper2, attrMapperDottedEmail, attrMapperNestedEmail);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -143,6 +143,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
|
|||
app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", true, true)).close();
|
||||
app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, true, true)).close();
|
||||
app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, true, true)).close();
|
||||
app.getProtocolMappers().createMapper(createClaimMapper("dotted phone", "phone", "home\\.phone", "String", true, true, true)).close();
|
||||
app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, true, true)).close();
|
||||
app.getProtocolMappers().createMapper(createClaimMapper("firstDepartment", "departments", "firstDepartment", "String", true, true, false)).close();
|
||||
app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded")).close();
|
||||
|
@ -170,6 +171,8 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
|
|||
assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street");
|
||||
assertNotNull(idToken.getOtherClaims().get("home_phone"));
|
||||
assertThat((List<String>) idToken.getOtherClaims().get("home_phone"), hasItems("617-777-6666"));
|
||||
assertNotNull(idToken.getOtherClaims().get("home.phone"));
|
||||
assertThat((List<String>) idToken.getOtherClaims().get("home.phone"), hasItems("617-777-6666"));
|
||||
assertEquals("coded", idToken.getOtherClaims().get("hard"));
|
||||
Map nested = (Map) idToken.getOtherClaims().get("nested");
|
||||
assertEquals("coded-nested", nested.get("hard"));
|
||||
|
@ -221,6 +224,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
|
|||
|| model.getName().equals("hard")
|
||||
|| model.getName().equals("hard-nested")
|
||||
|| model.getName().equals("custom phone")
|
||||
|| model.getName().equals("dotted phone")
|
||||
|| model.getName().equals("departments")
|
||||
|| model.getName().equals("firstDepartment")
|
||||
|| model.getName().equals("nested phone")
|
||||
|
|
|
@ -202,7 +202,7 @@ multivalued.tooltip=Indicates if attribute supports multiple values. If true, th
|
|||
selectRole.label=Select Role
|
||||
selectRole.tooltip=Enter role in the textbox to the left, or click this button to browse and select the role you want.
|
||||
tokenClaimName.label=Token Claim Name
|
||||
tokenClaimName.tooltip=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.
|
||||
tokenClaimName.tooltip=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. To prevent nesting and use dot literally, escape the dot with backslash (\\.).
|
||||
jsonType.label=Claim JSON Type
|
||||
jsonType.tooltip=JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.
|
||||
includeInIdToken.label=Add to ID token
|
||||
|
|
Loading…
Reference in a new issue