Details
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
index 674c9ff..2f40c21 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
@@ -17,14 +17,11 @@
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.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty;
-import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AddressClaimSet;
import org.keycloak.representations.IDToken;
@@ -34,7 +31,6 @@ import java.util.List;
import java.util.Map;
/**
- * Set the 'name' claim to be first + last name.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@@ -43,26 +39,39 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+ public static final String STREET = "street";
+
static {
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, AddressMapper.class);
+
+ configProperties.add(createConfigProperty(STREET));
+ configProperties.add(createConfigProperty(AddressClaimSet.LOCALITY));
+ configProperties.add(createConfigProperty(AddressClaimSet.REGION));
+ configProperties.add(createConfigProperty(AddressClaimSet.POSTAL_CODE));
+ configProperties.add(createConfigProperty(AddressClaimSet.COUNTRY));
+ configProperties.add(createConfigProperty(AddressClaimSet.FORMATTED));
+ }
+
+ protected static ProviderConfigProperty createConfigProperty(String claimName) {
+ ProviderConfigProperty property = new ProviderConfigProperty();
+ property.setName(getModelPropertyName(claimName));
+ property.setLabel("addressClaim." + claimName + ".label");
+ property.setHelpText("addressClaim." + claimName + ".tooltip");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ property.setDefaultValue(claimName);
+ return property;
+ }
+
+ public static String getModelPropertyName(String claimName) {
+ return "user.attribute." + claimName;
}
public static final String PROVIDER_ID = "oidc-address-mapper";
public static ProtocolMapperModel createAddressMapper() {
- Map<String, String> config;
- ProtocolMapperModel address = new ProtocolMapperModel();
- address.setName("address");
- address.setProtocolMapper(PROVIDER_ID);
- address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
- address.setConsentRequired(true);
- address.setConsentText("${address}");
- config = new HashMap<String, String>();
- config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
- config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
- address.setConfig(config);
- return address;
+ return createAddressMapper(true, true);
}
+
public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) {
Map<String, String> config;
ProtocolMapperModel address = new ProtocolMapperModel();
@@ -74,6 +83,14 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
config = new HashMap<String, String>();
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken));
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken));
+
+ config.put(getModelPropertyName(STREET), STREET);
+ config.put(getModelPropertyName(AddressClaimSet.LOCALITY), AddressClaimSet.LOCALITY);
+ config.put(getModelPropertyName(AddressClaimSet.REGION), AddressClaimSet.REGION);
+ config.put(getModelPropertyName(AddressClaimSet.POSTAL_CODE), AddressClaimSet.POSTAL_CODE);
+ config.put(getModelPropertyName(AddressClaimSet.COUNTRY), AddressClaimSet.COUNTRY);
+ config.put(getModelPropertyName(AddressClaimSet.FORMATTED), AddressClaimSet.FORMATTED);
+
address.setConfig(config);
return address;
}
@@ -107,12 +124,24 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
UserModel user = userSession.getUser();
AddressClaimSet addressSet = new AddressClaimSet();
- addressSet.setStreetAddress(user.getFirstAttribute("street"));
- addressSet.setLocality(user.getFirstAttribute("locality"));
- addressSet.setRegion(user.getFirstAttribute("region"));
- addressSet.setPostalCode(user.getFirstAttribute("postal_code"));
- addressSet.setCountry(user.getFirstAttribute("country"));
+ addressSet.setStreetAddress(getUserModelAttributeValue(user, mappingModel, STREET));
+ addressSet.setLocality(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.LOCALITY));
+ addressSet.setRegion(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.REGION));
+ addressSet.setPostalCode(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.POSTAL_CODE));
+ addressSet.setCountry(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.COUNTRY));
+ addressSet.setFormattedAddress(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.FORMATTED));
token.getOtherClaims().put("address", addressSet);
}
+ private String getUserModelAttributeValue(UserModel user, ProtocolMapperModel mappingModel, String claim) {
+ String modelPropertyName = getModelPropertyName(claim);
+ String userAttrName = mappingModel.getConfig().get(modelPropertyName);
+
+ if (userAttrName == null) {
+ userAttrName = claim;
+ }
+
+ return user.getFirstAttribute(userAttrName);
+ }
+
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java
index ac86d20..7ffcfdc 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java
@@ -29,7 +29,9 @@ 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.protocol.oidc.mappers.AddressMapper;
import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.AddressClaimSet;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
@@ -96,11 +98,13 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
user.singleAttribute("street", "5 Yawkey Way");
user.singleAttribute("locality", "Boston");
- user.singleAttribute("region", "MA");
+ user.singleAttribute("region_some", "MA"); // Custom name for userAttribute name, which will be mapped to region
user.singleAttribute("postal_code", "02115");
user.singleAttribute("country", "USA");
+ user.singleAttribute("formatted", "6 Foo Street");
user.singleAttribute("phone", "617-777-6666");
+
List<String> departments = Arrays.asList("finance", "development");
user.getAttributes().put("departments", departments);
userResource.update(user);
@@ -108,6 +112,9 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
+ mapper.getConfig().put(AddressMapper.getModelPropertyName(AddressClaimSet.REGION), "region_some");
+ mapper.getConfig().put(AddressMapper.getModelPropertyName(AddressClaimSet.COUNTRY), "country_some");
+ mapper.getConfig().remove(AddressMapper.getModelPropertyName(AddressClaimSet.POSTAL_CODE)); // Even if we remove protocolMapper config property, it should still default to postal_code
app.getProtocolMappers().createMapper(mapper);
ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
@@ -131,7 +138,8 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
assertEquals(idToken.getAddress().getLocality(), "Boston");
assertEquals(idToken.getAddress().getRegion(), "MA");
assertEquals(idToken.getAddress().getPostalCode(), "02115");
- assertEquals(idToken.getAddress().getCountry(), "USA");
+ assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country"
+ assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street");
assertNotNull(idToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
assertEquals("coded", idToken.getOtherClaims().get("hard"));
@@ -150,7 +158,8 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
assertEquals(accessToken.getAddress().getLocality(), "Boston");
assertEquals(accessToken.getAddress().getRegion(), "MA");
assertEquals(accessToken.getAddress().getPostalCode(), "02115");
- assertEquals(accessToken.getAddress().getCountry(), "USA");
+ assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country"
+ assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street");
assertNotNull(accessToken.getOtherClaims().get("home_phone"));
assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
assertEquals("coded", accessToken.getOtherClaims().get("hard"));
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 29f1465..8cf09f3 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -170,8 +170,18 @@ sectorIdentifierUri.label=Sector Identifier URI
sectorIdentifierUri.tooltip=Providers that use pairwise sub values and support Dynamic Client Registration SHOULD use the sector_identifier_uri parameter. It provides a way for a group of websites under common administrative control to have consistent pairwise sub values independent of the individual domain names. It also provides a way for Clients to change redirect_uri domains without having to reregister all of their users.
pairwiseSubAlgorithmSalt.label=Salt
pairwiseSubAlgorithmSalt.tooltip=Salt used when calculating the pairwise subject identifier. If left blank, a salt will be generated.
-
-
+addressClaim.street.label=User Attribute Name for Street
+addressClaim.street.tooltip=Name of User Attribute, which will be used to map to 'street_address' subclaim inside 'address' token claim. Defaults to 'street' .
+addressClaim.locality.label=User Attribute Name for Locality
+addressClaim.locality.tooltip=Name of User Attribute, which will be used to map to 'locality' subclaim inside 'address' token claim. Defaults to 'locality' .
+addressClaim.region.label=User Attribute Name for Region
+addressClaim.region.tooltip=Name of User Attribute, which will be used to map to 'region' subclaim inside 'address' token claim. Defaults to 'region' .
+addressClaim.postal_code.label=User Attribute Name for Postal Code
+addressClaim.postal_code.tooltip=Name of User Attribute, which will be used to map to 'postal_code' subclaim inside 'address' token claim. Defaults to 'postal_code' .
+addressClaim.country.label=User Attribute Name for Country
+addressClaim.country.tooltip=Name of User Attribute, which will be used to map to 'country' subclaim inside 'address' token claim. Defaults to 'country' .
+addressClaim.formatted.label=User Attribute Name for Formatted Address
+addressClaim.formatted.tooltip=Name of User Attribute, which will be used to map to 'formatted' subclaim inside 'address' token claim. Defaults to 'formatted' .
# client details
clients.tooltip=Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles.