From 9b870d3d8ac2e0f16674cd3f096d48073b17edee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20Kn=C3=BCppel?= Date: Mon, 1 Dec 2025 14:55:44 +0100 Subject: [PATCH] Fix ClassCastException on mixing AddressMapper with ClaimsMapper (#44457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #44455 Signed-off-by: Pascal Knüppel Signed-off-by: Captain-P-Goldfish --- .../representations/AddressClaimSet.java | 16 ++ .../org/keycloak/representations/IDToken.java | 26 +- .../keycloak/representations/UserInfo.java | 34 ++- .../keycloak/representations/IDTokenTest.java | 46 ++++ .../representations/UserInfoTest.java | 46 ++++ .../protocol/oidc/mappers/AddressMapper.java | 32 ++- .../oauth/OIDCProtocolMappersTest.java | 222 ++++++++++++++++-- .../testsuite/oidc/OIDCScopeTest.java | 2 +- 8 files changed, 389 insertions(+), 35 deletions(-) create mode 100644 core/src/test/java/org/keycloak/representations/IDTokenTest.java create mode 100644 core/src/test/java/org/keycloak/representations/UserInfoTest.java diff --git a/core/src/main/java/org/keycloak/representations/AddressClaimSet.java b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java index 30a1bba3537..b19fa2621d7 100755 --- a/core/src/main/java/org/keycloak/representations/AddressClaimSet.java +++ b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java @@ -17,6 +17,11 @@ package org.keycloak.representations; +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -49,6 +54,8 @@ public class AddressClaimSet { @JsonProperty(COUNTRY) protected String country; + protected Map otherClaims = new HashMap<>(); + public String getFormattedAddress() { return this.formattedAddress; } @@ -97,4 +104,13 @@ public class AddressClaimSet { this.country = country; } + @JsonAnyGetter + public Map getOtherClaims() { + return otherClaims; + } + + @JsonAnySetter + public void setOtherClaims(String name, Object value) { + otherClaims.put(name, value); + } } diff --git a/core/src/main/java/org/keycloak/representations/IDToken.java b/core/src/main/java/org/keycloak/representations/IDToken.java index 15e4f8c63e3..17383d851dc 100755 --- a/core/src/main/java/org/keycloak/representations/IDToken.java +++ b/core/src/main/java/org/keycloak/representations/IDToken.java @@ -17,7 +17,11 @@ package org.keycloak.representations; +import java.util.Map; +import java.util.Optional; + import org.keycloak.TokenCategory; +import org.keycloak.util.JsonSerialization; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -127,7 +131,7 @@ public class IDToken extends JsonWebToken { protected Boolean phoneNumberVerified; @JsonProperty(ADDRESS) - protected AddressClaimSet address; + protected Map address; @JsonProperty(UPDATED_AT) protected Long updatedAt; @@ -328,14 +332,30 @@ public class IDToken extends JsonWebToken { this.phoneNumberVerified = phoneNumberVerified; } - public AddressClaimSet getAddress() { + @JsonProperty("address") + public Map getAddressClaimsMap() { return address; } - public void setAddress(AddressClaimSet address) { + @JsonIgnore + public AddressClaimSet getAddress() { + return Optional.ofNullable(address).map(a -> { + return JsonSerialization.mapper.convertValue(a, AddressClaimSet.class); + }) + .orElse(null); + } + + public void setAddress(Map address) { this.address = address; } + @JsonIgnore + public void setAddress(AddressClaimSet address) { + this.address = Optional.ofNullable(address) + .map(a -> JsonSerialization.mapper.convertValue(a, Map.class)) + .orElse(null); + } + public Long getUpdatedAt() { return this.updatedAt; } diff --git a/core/src/main/java/org/keycloak/representations/UserInfo.java b/core/src/main/java/org/keycloak/representations/UserInfo.java index e6989f56dba..f7e421747c6 100755 --- a/core/src/main/java/org/keycloak/representations/UserInfo.java +++ b/core/src/main/java/org/keycloak/representations/UserInfo.java @@ -16,11 +16,14 @@ */ package org.keycloak.representations; +import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.keycloak.json.StringOrArrayDeserializer; import org.keycloak.json.StringOrArraySerializer; +import org.keycloak.util.JsonSerialization; import com.fasterxml.jackson.annotation.JsonAnyGetter; import com.fasterxml.jackson.annotation.JsonAnySetter; @@ -97,7 +100,7 @@ public class UserInfo { protected Boolean phoneNumberVerified; @JsonProperty("address") - protected AddressClaimSet address; + protected Map address; @JsonProperty("updated_at") protected Long updatedAt; @@ -277,14 +280,30 @@ public class UserInfo { this.phoneNumberVerified = phoneNumberVerified; } - public AddressClaimSet getAddress() { + @JsonProperty("address") + public Map getAddressClaimsMap() { return address; } - public void setAddress(AddressClaimSet address) { + @JsonIgnore + public AddressClaimSet getAddress() { + return Optional.ofNullable(address).map(a -> { + return JsonSerialization.mapper.convertValue(a, AddressClaimSet.class); + }) + .orElse(null); + } + + public void setAddress(Map address) { this.address = address; } + @JsonIgnore + public void setAddress(AddressClaimSet address) { + this.address = Optional.ofNullable(address) + .map(a -> JsonSerialization.mapper.convertValue(a, Map.class)) + .orElse(null); + } + public Long getUpdatedAt() { return this.updatedAt; } @@ -323,4 +342,13 @@ public class UserInfo { public void setOtherClaims(String name, Object value) { otherClaims.put(name, value); } + + @Override + public String toString() { + try { + return JsonSerialization.writeValueAsString(this); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/core/src/test/java/org/keycloak/representations/IDTokenTest.java b/core/src/test/java/org/keycloak/representations/IDTokenTest.java new file mode 100644 index 00000000000..3d7f262eecd --- /dev/null +++ b/core/src/test/java/org/keycloak/representations/IDTokenTest.java @@ -0,0 +1,46 @@ +package org.keycloak.representations; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Pascal Knueppel + * @since 28.11.2025 + */ +public class IDTokenTest { + + /** + * makes sure that the setAddress and getAddress method for the idToken works as expected + */ + @Test + public void testSetAddressMethodWorks() { + AddressClaimSet addressClaimSet = new AddressClaimSet(); + addressClaimSet.setFormattedAddress("test"); + addressClaimSet.setCountry("test1"); + addressClaimSet.setLocality("test2"); + addressClaimSet.setStreetAddress("test3"); + addressClaimSet.setRegion("test4"); + addressClaimSet.setPostalCode("test5"); + + IDToken idToken = new IDToken(); + idToken.setAddress(addressClaimSet); + + AddressClaimSet parsedAddress = idToken.getAddress(); + Assert.assertEquals(addressClaimSet.getFormattedAddress(), parsedAddress.getFormattedAddress()); + Assert.assertEquals(addressClaimSet.getStreetAddress(), parsedAddress.getStreetAddress()); + Assert.assertEquals(addressClaimSet.getCountry(), parsedAddress.getCountry()); + Assert.assertEquals(addressClaimSet.getLocality(), parsedAddress.getLocality()); + Assert.assertEquals(addressClaimSet.getRegion(), parsedAddress.getRegion()); + Assert.assertEquals(addressClaimSet.getPostalCode(), parsedAddress.getPostalCode()); + + Map addressClaimsSet = idToken.getAddressClaimsMap(); + Assert.assertEquals(addressClaimSet.getFormattedAddress(), addressClaimsSet.get("formatted")); + Assert.assertEquals(addressClaimSet.getStreetAddress(), addressClaimsSet.get("street_address")); + Assert.assertEquals(addressClaimSet.getCountry(), addressClaimsSet.get("country")); + Assert.assertEquals(addressClaimSet.getLocality(), addressClaimsSet.get("locality")); + Assert.assertEquals(addressClaimSet.getRegion(), addressClaimsSet.get("region")); + Assert.assertEquals(addressClaimSet.getPostalCode(), addressClaimsSet.get("postal_code")); + } +} diff --git a/core/src/test/java/org/keycloak/representations/UserInfoTest.java b/core/src/test/java/org/keycloak/representations/UserInfoTest.java new file mode 100644 index 00000000000..6bd1e5d49ca --- /dev/null +++ b/core/src/test/java/org/keycloak/representations/UserInfoTest.java @@ -0,0 +1,46 @@ +package org.keycloak.representations; + +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Pascal Knueppel + * @since 28.11.2025 + */ +public class UserInfoTest { + + /** + * makes sure that the setAddress and getAddress method for the userInfo works as expected + */ + @Test + public void testSetAddressMethodWorks() { + AddressClaimSet addressClaimSet = new AddressClaimSet(); + addressClaimSet.setFormattedAddress("test"); + addressClaimSet.setCountry("test1"); + addressClaimSet.setLocality("test2"); + addressClaimSet.setStreetAddress("test3"); + addressClaimSet.setRegion("test4"); + addressClaimSet.setPostalCode("test5"); + + UserInfo userInfo = new UserInfo(); + userInfo.setAddress(addressClaimSet); + + AddressClaimSet parsedAddress = userInfo.getAddress(); + Assert.assertEquals(addressClaimSet.getFormattedAddress(), parsedAddress.getFormattedAddress()); + Assert.assertEquals(addressClaimSet.getStreetAddress(), parsedAddress.getStreetAddress()); + Assert.assertEquals(addressClaimSet.getCountry(), parsedAddress.getCountry()); + Assert.assertEquals(addressClaimSet.getLocality(), parsedAddress.getLocality()); + Assert.assertEquals(addressClaimSet.getRegion(), parsedAddress.getRegion()); + Assert.assertEquals(addressClaimSet.getPostalCode(), parsedAddress.getPostalCode()); + + Map addressClaimsSet = userInfo.getAddressClaimsMap(); + Assert.assertEquals(addressClaimSet.getFormattedAddress(), addressClaimsSet.get("formatted")); + Assert.assertEquals(addressClaimSet.getStreetAddress(), addressClaimsSet.get("street_address")); + Assert.assertEquals(addressClaimSet.getCountry(), addressClaimsSet.get("country")); + Assert.assertEquals(addressClaimSet.getLocality(), addressClaimsSet.get("locality")); + Assert.assertEquals(addressClaimSet.getRegion(), addressClaimsSet.get("region")); + Assert.assertEquals(addressClaimSet.getPostalCode(), addressClaimsSet.get("postal_code")); + } +} 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 9b3a7dffda8..741c8c08c01 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 @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.UserModel; @@ -123,14 +124,29 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc @Override protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) { UserModel user = userSession.getUser(); - AddressClaimSet addressSet = new AddressClaimSet(); - 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); + Map addressSet = Optional.ofNullable(token.getAddressClaimsMap()).orElseGet(() -> { + return Optional.ofNullable(token.getOtherClaims().get(IDToken.ADDRESS)) + .filter(Map.class::isInstance) + .map(o -> (HashMap) o) + .orElseGet(HashMap::new); + }); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, STREET)) + .ifPresent(street -> addressSet.put(AddressClaimSet.STREET_ADDRESS, street)); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.LOCALITY)) + .ifPresent(locality -> addressSet.put(AddressClaimSet.LOCALITY, locality)); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.REGION)) + .ifPresent(region -> addressSet.put(AddressClaimSet.REGION, region)); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.POSTAL_CODE)) + .ifPresent(postalCode -> addressSet.put(AddressClaimSet.POSTAL_CODE, postalCode)); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.COUNTRY)) + .ifPresent(country -> addressSet.put(AddressClaimSet.COUNTRY, country)); + Optional.ofNullable(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.FORMATTED)) + .ifPresent(formatted -> addressSet.put(AddressClaimSet.FORMATTED, formatted)); + + if (!addressSet.isEmpty()) { + token.setAddress(addressSet); + token.getOtherClaims().put(IDToken.ADDRESS, addressSet); + } } private String getUserModelAttributeValue(UserModel user, ProtocolMapperModel mappingModel, String claim) { 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 ac0f640232c..54e24f220bd 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 @@ -74,6 +74,7 @@ import org.keycloak.testsuite.util.oauth.AuthorizationEndpointResponse; import org.keycloak.testsuite.util.userprofile.UserProfileUtil; import org.hamcrest.CoreMatchers; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -132,6 +133,15 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { UserProfileUtil.enableUnmanagedAttributes(upResource); } + @After + public void cleanTestUserAttributes() { + UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost"); + UserRepresentation user = userResource.toRepresentation(); + // rollback user-changes + user.setAttributes(new HashMap<>()); + userResource.update(user); + } + private void deleteMappers(ProtocolMappersResource protocolMappers) { ProtocolMapperRepresentation mapper = ProtocolMapperUtil.getMapperByNameAndProtocol(protocolMappers, OIDCLoginProtocol.LOGIN_PROTOCOL, "Realm roles mapper"); @@ -187,8 +197,177 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { } @Test - - public void testTokenMapping() throws Exception { + public void testAddressMappingWithAdditionalMapper() { + // prepare test + { + 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("formatted", "6 Foo Street"); + user.singleAttribute("address_type", "STRUCTURED"); + + userResource.update(user); + + ProtocolMapperRepresentation addressMapper = createAddressMapper(true, true, true, true); + ProtocolMapperRepresentation addressTypeMapper = createClaimMapper("additional-address-field", + "address_type", + "address.type", + "String", + true, + true, + true, + false); + + + ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app"); + app.getProtocolMappers().createMapper(addressMapper).close(); + app.getProtocolMappers().createMapper(addressTypeMapper).close(); + } + + { + AccessTokenResponse response = browserLogin("test-user@localhost", "password"); + IDToken idToken = oauth.verifyIDToken(response.getIdToken()); + + assertNotNull(idToken.getAddress()); + AddressClaimSet idTokenAddress = idToken.getAddress(); + assertEquals("Tom Brady", idToken.getName()); + assertEquals("5 Yawkey Way", idTokenAddress.getStreetAddress()); + assertEquals("Boston", idTokenAddress.getLocality()); + assertEquals("MA", idTokenAddress.getRegion()); + assertEquals("02115", idTokenAddress.getPostalCode()); + assertEquals("USA", idTokenAddress.getCountry()); + assertEquals("STRUCTURED", idTokenAddress.getOtherClaims().get("type")); + } + + // 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("additional-address-field")) { + app.getProtocolMappers().delete(model.getId()); + } + } + } + + events.clear(); + } + + @Test + public void testAddressMappingWithAdditionalMapperReversedOrder() { + // prepare test + { + 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("formatted", "6 Foo Street"); + user.singleAttribute("address_type", "STRUCTURED"); + + userResource.update(user); + + ProtocolMapperRepresentation addressTypeMapper = createClaimMapper("additional-address-field", + "address_type", + "address.type", + "String", + true, + true, + true, + false); + ProtocolMapperRepresentation addressMapper = createAddressMapper(true, true, true, true); + + + ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app"); + app.getProtocolMappers().createMapper(addressMapper).close(); + app.getProtocolMappers().createMapper(addressTypeMapper).close(); + } + + { + AccessTokenResponse response = browserLogin("test-user@localhost", "password"); + IDToken idToken = oauth.verifyIDToken(response.getIdToken()); + + assertNotNull(idToken.getAddress()); + AddressClaimSet idTokenAddress = idToken.getAddress(); + assertEquals("Tom Brady", idToken.getName()); + assertEquals("5 Yawkey Way", idTokenAddress.getStreetAddress()); + assertEquals("Boston", idTokenAddress.getLocality()); + assertEquals("MA", idTokenAddress.getRegion()); + assertEquals("02115", idTokenAddress.getPostalCode()); + assertEquals("USA", idTokenAddress.getCountry()); + assertEquals("STRUCTURED", idTokenAddress.getOtherClaims().get("type")); + } + + // 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("additional-address-field")) { + app.getProtocolMappers().delete(model.getId()); + } + } + } + + events.clear(); + } + + @Test + public void testAddressMappingWithoutPresentAddress() { + // prepare test + { + UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost"); + // user has no address + UserRepresentation user = userResource.toRepresentation(); + + userResource.update(user); + + ProtocolMapperRepresentation addressTypeMapper = createClaimMapper("additional-address-field", + "address_type", + "address.type", + "String", + true, + true, + true, + false); + ProtocolMapperRepresentation addressMapper = createAddressMapper(true, true, true, true); + + ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app"); + app.getProtocolMappers().createMapper(addressMapper).close(); + app.getProtocolMappers().createMapper(addressTypeMapper).close(); + } + + { + AccessTokenResponse response = browserLogin("test-user@localhost", "password"); + IDToken idToken = oauth.verifyIDToken(response.getIdToken()); + + assertNull(idToken.getAddress()); + } + + // 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("additional-address-field")) { + app.getProtocolMappers().delete(model.getId()); + } + } + } + + events.clear(); + } + + @Test + public void testTokenMapping() { { UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost"); UserRepresentation user = userResource.toRepresentation(); @@ -247,13 +426,14 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { 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"); - assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" - assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street"); + AddressClaimSet idTokenAddress = idToken.getAddress(); + assertEquals("Tom Brady", idToken.getName()); + assertEquals("5 Yawkey Way", idTokenAddress.getStreetAddress()); + assertEquals("Boston", idTokenAddress.getLocality()); + assertEquals("MA", idTokenAddress.getRegion()); + assertEquals("02115", idTokenAddress.getPostalCode()); + assertNull(idTokenAddress.getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" + assertEquals("6 Foo Street", idTokenAddress.getFormattedAddress()); assertNotNull(idToken.getOtherClaims().get("home_phone")); assertThat((List) idToken.getOtherClaims().get("home_phone"), hasItems("617-777-6666")); assertNotNull(idToken.getOtherClaims().get("home.phone")); @@ -284,13 +464,15 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { 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"); - assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" - assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street"); + AddressClaimSet accessTokenAddress = accessToken.getAddress(); + assertEquals("5 Yawkey Way", accessTokenAddress.getStreetAddress()); + assertEquals("Boston", accessTokenAddress.getLocality()); + assertEquals("MA", accessTokenAddress.getRegion()); + assertEquals("02115", accessTokenAddress.getPostalCode()); + assertNull(accessTokenAddress.getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" + assertEquals("6 Foo Street", accessTokenAddress.getFormattedAddress()); assertNotNull(accessToken.getOtherClaims().get("home_phone")); assertThat((List) accessToken.getOtherClaims().get("home_phone"), hasItems("617-777-6666")); assertEquals("coded", accessToken.getOtherClaims().get("hard")); @@ -369,7 +551,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { } @Test - + public void testTokenPropertiesMapping() throws Exception { UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost"); UserRepresentation user = userResource.toRepresentation(); @@ -529,7 +711,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { } @Test - + public void testNullOrEmptyTokenMapping() throws Exception { { UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost"); @@ -587,7 +769,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { @Test - + public void testUserRoleToAttributeMappers() throws Exception { // Add mapper for realm roles ProtocolMapperRepresentation realmMapper = ProtocolMapperUtil.createUserRealmRoleMappingMapper("pref.", "Realm roles mapper", "roles-custom.realm", true, true, true); @@ -620,7 +802,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { // Test to update protocolMappers to not have roles on the default position (realm_access and resource_access properties) @Test - + public void testUserRolesMovedFromAccessTokenProperties() throws Exception { RealmResource realm = adminClient.realm("test"); ClientScopeResource rolesScope = ApiUtil.findClientScopeByName(realm, OIDCLoginProtocolFactory.ROLES_SCOPE); @@ -842,7 +1024,7 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest { @Test - + public void testUserGroupRoleToAttributeMappers() throws Exception { // Add mapper for realm roles String clientId = "test-app"; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java index 63389c1ea52..c28bd0d201a 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCScopeTest.java @@ -173,7 +173,7 @@ public class OIDCScopeTest extends AbstractOIDCScopeTest { } } - + @Test public void testBuiltinOptionalScopes() throws Exception { // Login. Assert that just 'profile' and 'email' data are there. 'Address' and 'phone' not