diff --git a/core/src/main/java/org/keycloak/representations/AddressClaimSet.java b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java new file mode 100755 index 0000000000..4b47b8f6f9 --- /dev/null +++ b/core/src/main/java/org/keycloak/representations/AddressClaimSet.java @@ -0,0 +1,76 @@ +package org.keycloak.representations; + +import org.codehaus.jackson.annotate.JsonProperty; + +/** +* @author Bill Burke +* @version $Revision: 1 $ +*/ +public class AddressClaimSet { + @JsonProperty("formatted") + protected String formattedAddress; + + @JsonProperty("street_address") + protected String streetAddress; + + @JsonProperty("locality") + protected String locality; + + @JsonProperty("region") + protected String region; + + @JsonProperty("postal_code") + protected String postalCode; + + @JsonProperty("country") + protected String country; + + public String getFormattedAddress() { + return this.formattedAddress; + } + + public void setFormattedAddress(String formattedAddress) { + this.formattedAddress = formattedAddress; + } + + public String getStreetAddress() { + return this.streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public String getLocality() { + return this.locality; + } + + public void setLocality(String locality) { + this.locality = locality; + } + + public String getRegion() { + return this.region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getPostalCode() { + return this.postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public String getCountry() { + return this.country; + } + + public void setCountry(String country) { + this.country = country; + } + +} diff --git a/core/src/main/java/org/keycloak/representations/IDToken.java b/core/src/main/java/org/keycloak/representations/IDToken.java index fa58c9e0fd..523d1f13f9 100755 --- a/core/src/main/java/org/keycloak/representations/IDToken.java +++ b/core/src/main/java/org/keycloak/representations/IDToken.java @@ -13,15 +13,73 @@ import java.util.Map; * @version $Revision: 1 $ */ public class IDToken extends JsonWebToken { - + // NOTE!!! WE used to use @JsonUnwrapped on a UserClaimSet object. This screws up otherClaims and the won't work + // anymore. So don't have any @JsonUnwrapped! @JsonProperty("nonce") protected String nonce; @JsonProperty("session_state") protected String sessionState; - @JsonUnwrapped - protected UserClaimSet userClaimSet = new UserClaimSet(); + @JsonProperty("name") + protected String name; + + @JsonProperty("given_name") + protected String givenName; + + @JsonProperty("family_name") + protected String familyName; + + @JsonProperty("middle_name") + protected String middleName; + + @JsonProperty("nickname") + protected String nickName; + + @JsonProperty("preferred_username") + protected String preferredUsername; + + @JsonProperty("profile") + protected String profile; + + @JsonProperty("picture") + protected String picture; + + @JsonProperty("website") + protected String website; + + @JsonProperty("email") + protected String email; + + @JsonProperty("email_verified") + protected Boolean emailVerified; + + @JsonProperty("gender") + protected String gender; + + @JsonProperty("birthdate") + protected String birthdate; + + @JsonProperty("zoneinfo") + protected String zoneinfo; + + @JsonProperty("locale") + protected String locale; + + @JsonProperty("phone_number") + protected String phoneNumber; + + @JsonProperty("phone_number_verified") + protected Boolean phoneNumberVerified; + + @JsonProperty("address") + protected AddressClaimSet address; + + @JsonProperty("updated_at") + protected Long updatedAt; + + @JsonProperty("claims_locales") + protected String claimsLocales; protected Map otherClaims = new HashMap(); @@ -41,17 +99,166 @@ public class IDToken extends JsonWebToken { this.sessionState = sessionState; } - /** - * Standardized OpenID Connect claims - * - * @return - */ - public UserClaimSet getUserClaimSet() { - return this.userClaimSet; + + + public String getName() { + return this.name; } - public void setUserClaimSet(UserClaimSet userClaimSet) { - this.userClaimSet = userClaimSet; + public void setName(String name) { + this.name = name; + } + + public String getGivenName() { + return this.givenName; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + } + + public String getFamilyName() { + return this.familyName; + } + + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + public String getMiddleName() { + return this.middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getNickName() { + return this.nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getPreferredUsername() { + return this.preferredUsername; + } + + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + + public String getProfile() { + return this.profile; + } + + public void setProfile(String profile) { + this.profile = profile; + } + + public String getPicture() { + return this.picture; + } + + public void setPicture(String picture) { + this.picture = picture; + } + + public String getWebsite() { + return this.website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Boolean getEmailVerified() { + return this.emailVerified; + } + + public void setEmailVerified(Boolean emailVerified) { + this.emailVerified = emailVerified; + } + + public String getGender() { + return this.gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getBirthdate() { + return this.birthdate; + } + + public void setBirthdate(String birthdate) { + this.birthdate = birthdate; + } + + public String getZoneinfo() { + return this.zoneinfo; + } + + public void setZoneinfo(String zoneinfo) { + this.zoneinfo = zoneinfo; + } + + public String getLocale() { + return this.locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getPhoneNumber() { + return this.phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public Boolean getPhoneNumberVerified() { + return this.phoneNumberVerified; + } + + public void setPhoneNumberVerified(Boolean phoneNumberVerified) { + this.phoneNumberVerified = phoneNumberVerified; + } + + public AddressClaimSet getAddress() { + return address; + } + + public void setAddress(AddressClaimSet address) { + this.address = address; + } + + public Long getUpdatedAt() { + return this.updatedAt; + } + + public void setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + } + + public String getClaimsLocales() { + return this.claimsLocales; + } + + public void setClaimsLocales(String claimsLocales) { + this.claimsLocales = claimsLocales; } /** @@ -65,7 +272,7 @@ public class IDToken extends JsonWebToken { } @JsonAnySetter - public void setOtherClaims(Map otherClaims) { - this.otherClaims = otherClaims; + public void setOtherClaims(String name, Object value) { + otherClaims.put(name, value); } } diff --git a/core/src/main/java/org/keycloak/representations/UserClaimSet.java b/core/src/main/java/org/keycloak/representations/UserClaimSet.java deleted file mode 100755 index 4e8f1f9f57..0000000000 --- a/core/src/main/java/org/keycloak/representations/UserClaimSet.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * JBoss, Home of Professional Open Source - * - * Copyright 2013 Red Hat, Inc. and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.representations; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * @author pedroigor - */ -public class UserClaimSet { - - public static class AddressClaimSet { - @JsonProperty("formatted") - protected String formattedAddress; - - @JsonProperty("street_address") - protected String streetAddress; - - @JsonProperty("locality") - protected String locality; - - @JsonProperty("region") - protected String region; - - @JsonProperty("postal_code") - protected String postalCode; - - @JsonProperty("country") - protected String country; - - public String getFormattedAddress() { - return this.formattedAddress; - } - - public void setFormattedAddress(String formattedAddress) { - this.formattedAddress = formattedAddress; - } - - public String getStreetAddress() { - return this.streetAddress; - } - - public void setStreetAddress(String streetAddress) { - this.streetAddress = streetAddress; - } - - public String getLocality() { - return this.locality; - } - - public void setLocality(String locality) { - this.locality = locality; - } - - public String getRegion() { - return this.region; - } - - public void setRegion(String region) { - this.region = region; - } - - public String getPostalCode() { - return this.postalCode; - } - - public void setPostalCode(String postalCode) { - this.postalCode = postalCode; - } - - public String getCountry() { - return this.country; - } - - public void setCountry(String country) { - this.country = country; - } - - } - - @JsonProperty("sub") - protected String sub; - - @JsonProperty("name") - protected String name; - - @JsonProperty("given_name") - protected String givenName; - - @JsonProperty("family_name") - protected String familyName; - - @JsonProperty("middle_name") - protected String middleName; - - @JsonProperty("nickname") - protected String nickName; - - @JsonProperty("preferred_username") - protected String preferredUsername; - - @JsonProperty("profile") - protected String profile; - - @JsonProperty("picture") - protected String picture; - - @JsonProperty("website") - protected String website; - - @JsonProperty("email") - protected String email; - - @JsonProperty("email_verified") - protected Boolean emailVerified; - - @JsonProperty("gender") - protected String gender; - - @JsonProperty("birthdate") - protected String birthdate; - - @JsonProperty("zoneinfo") - protected String zoneinfo; - - @JsonProperty("locale") - protected String locale; - - @JsonProperty("phone_number") - protected String phoneNumber; - - @JsonProperty("phone_number_verified") - protected Boolean phoneNumberVerified; - - @JsonProperty("address") - protected AddressClaimSet address; - - @JsonProperty("updated_at") - protected Long updatedAt; - - @JsonProperty("claims_locales") - protected String claimsLocales; - - public String getSubject() { - return this.sub; - } - - public void setSubject(String subject) { - this.sub = subject; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getGivenName() { - return this.givenName; - } - - public void setGivenName(String givenName) { - this.givenName = givenName; - } - - public String getFamilyName() { - return this.familyName; - } - - public void setFamilyName(String familyName) { - this.familyName = familyName; - } - - public String getMiddleName() { - return this.middleName; - } - - public void setMiddleName(String middleName) { - this.middleName = middleName; - } - - public String getNickName() { - return this.nickName; - } - - public void setNickName(String nickName) { - this.nickName = nickName; - } - - public String getPreferredUsername() { - return this.preferredUsername; - } - - public void setPreferredUsername(String preferredUsername) { - this.preferredUsername = preferredUsername; - } - - public String getProfile() { - return this.profile; - } - - public void setProfile(String profile) { - this.profile = profile; - } - - public String getPicture() { - return this.picture; - } - - public void setPicture(String picture) { - this.picture = picture; - } - - public String getWebsite() { - return this.website; - } - - public void setWebsite(String website) { - this.website = website; - } - - public String getEmail() { - return this.email; - } - - public void setEmail(String email) { - this.email = email; - } - - public Boolean getEmailVerified() { - return this.emailVerified; - } - - public void setEmailVerified(Boolean emailVerified) { - this.emailVerified = emailVerified; - } - - public String getGender() { - return this.gender; - } - - public void setGender(String gender) { - this.gender = gender; - } - - public String getBirthdate() { - return this.birthdate; - } - - public void setBirthdate(String birthdate) { - this.birthdate = birthdate; - } - - public String getZoneinfo() { - return this.zoneinfo; - } - - public void setZoneinfo(String zoneinfo) { - this.zoneinfo = zoneinfo; - } - - public String getLocale() { - return this.locale; - } - - public void setLocale(String locale) { - this.locale = locale; - } - - public String getPhoneNumber() { - return this.phoneNumber; - } - - public void setPhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - - public Boolean getPhoneNumberVerified() { - return this.phoneNumberVerified; - } - - public void setPhoneNumberVerified(Boolean phoneNumberVerified) { - this.phoneNumberVerified = phoneNumberVerified; - } - - public AddressClaimSet getAddress() { - return address; - } - - public void setAddress(AddressClaimSet address) { - this.address = address; - } - - public Long getUpdatedAt() { - return this.updatedAt; - } - - public void setUpdatedAt(Long updatedAt) { - this.updatedAt = updatedAt; - } - - public String getSub() { - return this.sub; - } - - public void setSub(String sub) { - this.sub = sub; - } - - public String getClaimsLocales() { - return this.claimsLocales; - } - - public void setClaimsLocales(String claimsLocales) { - this.claimsLocales = claimsLocales; - } -} diff --git a/core/src/main/java/org/keycloak/representations/UserInfo.java b/core/src/main/java/org/keycloak/representations/UserInfo.java old mode 100644 new mode 100755 index 311298115f..d9542fa735 --- a/core/src/main/java/org/keycloak/representations/UserInfo.java +++ b/core/src/main/java/org/keycloak/representations/UserInfo.java @@ -17,9 +17,248 @@ */ package org.keycloak.representations; +import org.codehaus.jackson.annotate.JsonProperty; + /** * @author pedroigor */ -public class UserInfo extends UserClaimSet { +public class UserInfo { + @JsonProperty("sub") + protected String sub; + @JsonProperty("name") + protected String name; + + @JsonProperty("given_name") + protected String givenName; + + @JsonProperty("family_name") + protected String familyName; + + @JsonProperty("middle_name") + protected String middleName; + + @JsonProperty("nickname") + protected String nickName; + + @JsonProperty("preferred_username") + protected String preferredUsername; + + @JsonProperty("profile") + protected String profile; + + @JsonProperty("picture") + protected String picture; + + @JsonProperty("website") + protected String website; + + @JsonProperty("email") + protected String email; + + @JsonProperty("email_verified") + protected Boolean emailVerified; + + @JsonProperty("gender") + protected String gender; + + @JsonProperty("birthdate") + protected String birthdate; + + @JsonProperty("zoneinfo") + protected String zoneinfo; + + @JsonProperty("locale") + protected String locale; + + @JsonProperty("phone_number") + protected String phoneNumber; + + @JsonProperty("phone_number_verified") + protected Boolean phoneNumberVerified; + + @JsonProperty("address") + protected AddressClaimSet address; + + @JsonProperty("updated_at") + protected Long updatedAt; + + @JsonProperty("claims_locales") + protected String claimsLocales; + + public String getSubject() { + return this.sub; + } + + public void setSubject(String subject) { + this.sub = subject; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGivenName() { + return this.givenName; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + } + + public String getFamilyName() { + return this.familyName; + } + + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + public String getMiddleName() { + return this.middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getNickName() { + return this.nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getPreferredUsername() { + return this.preferredUsername; + } + + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + + public String getProfile() { + return this.profile; + } + + public void setProfile(String profile) { + this.profile = profile; + } + + public String getPicture() { + return this.picture; + } + + public void setPicture(String picture) { + this.picture = picture; + } + + public String getWebsite() { + return this.website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Boolean getEmailVerified() { + return this.emailVerified; + } + + public void setEmailVerified(Boolean emailVerified) { + this.emailVerified = emailVerified; + } + + public String getGender() { + return this.gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getBirthdate() { + return this.birthdate; + } + + public void setBirthdate(String birthdate) { + this.birthdate = birthdate; + } + + public String getZoneinfo() { + return this.zoneinfo; + } + + public void setZoneinfo(String zoneinfo) { + this.zoneinfo = zoneinfo; + } + + public String getLocale() { + return this.locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getPhoneNumber() { + return this.phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public Boolean getPhoneNumberVerified() { + return this.phoneNumberVerified; + } + + public void setPhoneNumberVerified(Boolean phoneNumberVerified) { + this.phoneNumberVerified = phoneNumberVerified; + } + + public AddressClaimSet getAddress() { + return address; + } + + public void setAddress(AddressClaimSet address) { + this.address = address; + } + + public Long getUpdatedAt() { + return this.updatedAt; + } + + public void setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + } + + public String getSub() { + return this.sub; + } + + public void setSub(String sub) { + this.sub = sub; + } + + public String getClaimsLocales() { + return this.claimsLocales; + } + + public void setClaimsLocales(String claimsLocales) { + this.claimsLocales = claimsLocales; + } } diff --git a/core/src/test/java/org/keycloak/JsonParserTest.java b/core/src/test/java/org/keycloak/JsonParserTest.java index 7929495290..1f51c2154f 100755 --- a/core/src/test/java/org/keycloak/JsonParserTest.java +++ b/core/src/test/java/org/keycloak/JsonParserTest.java @@ -26,6 +26,7 @@ public class JsonParserTest { IDToken test = new IDToken(); test.getOtherClaims().put("phone_number", "978-666-0000"); test.getOtherClaims().put("email_verified", "true"); + test.getOtherClaims().put("yo", "true"); Map nested = new HashMap(); nested.put("foo", "bar"); test.getOtherClaims().put("nested", nested); @@ -33,11 +34,15 @@ public class JsonParserTest { System.out.println(json); test = JsonSerialization.readValue(json, IDToken.class); - System.out.println("email_verified property: " + test.getUserClaimSet().getEmailVerified()); - System.out.println("property: " + test.getUserClaimSet().getPhoneNumber()); + System.out.println("email_verified property: " + test.getEmailVerified()); + System.out.println("property: " + test.getPhoneNumber()); System.out.println("map: " + test.getOtherClaims().get("phone_number")); - Assert.assertNotNull(test.getUserClaimSet().getPhoneNumber()); + Assert.assertNotNull(test.getPhoneNumber()); + Assert.assertNotNull(test.getOtherClaims().get("yo")); Assert.assertNull(test.getOtherClaims().get("phone_number")); + nested = (Map)test.getOtherClaims().get("nested"); + Assert.assertNotNull(nested); + Assert.assertNotNull(nested.get("foo")); } @Test diff --git a/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java b/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java index e5a332d2e3..268cddd728 100755 --- a/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java +++ b/core/src/test/java/org/keycloak/SkeletonKeyTokenTest.java @@ -6,7 +6,6 @@ import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.representations.AccessToken; -import org.keycloak.representations.UserClaimSet; import org.keycloak.representations.IDToken; import org.keycloak.util.JsonSerialization; @@ -59,9 +58,8 @@ public class SkeletonKeyTokenTest { public void testSerialization() throws Exception { AccessToken token = createSimpleToken(); IDToken idToken = new IDToken(); - UserClaimSet claimSet = idToken.getUserClaimSet(); - claimSet.setEmail("joe@email.cz"); + idToken.setEmail("joe@email.cz"); KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); @@ -98,7 +96,7 @@ public class SkeletonKeyTokenTest { Assert.assertEquals("111", token.getId()); Assert.assertTrue(token.getResourceAccess("foo").isUserInRole("admin")); Assert.assertTrue(token.getResourceAccess("bar").isUserInRole("user")); - Assert.assertEquals("joe@email.cz", claimSet.getEmail()); + Assert.assertEquals("joe@email.cz", idToken.getEmail()); Assert.assertEquals("acme", ctx.getRealm()); ois.close(); } diff --git a/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp b/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp index 2eb5e6605a..04a54bb1e6 100755 --- a/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp +++ b/examples/demo-template/customer-app/src/main/webapp/customers/view.jsp @@ -3,7 +3,6 @@ <%@ page import="org.keycloak.constants.ServiceUrlConstants" %> <%@ page import="org.keycloak.example.CustomerDatabaseClient" %> <%@ page import="org.keycloak.representations.IDToken" %> -<%@ page import="org.keycloak.representations.UserClaimSet" %> <%@ page import="org.keycloak.util.KeycloakUriBuilder" %> <%@ page session="false" %> @@ -17,18 +16,17 @@ String acctUri = KeycloakUriBuilder.fromUri("/auth").path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH) .queryParam("referrer", "customer-portal").build("demo").toString(); IDToken idToken = CustomerDatabaseClient.getIDToken(request); - UserClaimSet claims = idToken.getUserClaimSet(); %>

Goto: products | logout | manage acct

Servlet User Principal <%=request.getUserPrincipal().getName()%> made this request.

Caller IDToken values (You can specify what is returned in IDToken in the customer-portal claims page in the admin console:

-

Username: <%=claims.getPreferredUsername()%>

-

Email: <%=claims.getEmail()%>

-

Full Name: <%=claims.getName()%>

-

First: <%=claims.getGivenName()%>

-

Last: <%=claims.getFamilyName()%>

+

Username: <%=idToken.getPreferredUsername()%>

+

Email: <%=idToken.getEmail()%>

+

Full Name: <%=idToken.getName()%>

+

First: <%=idToken.getGivenName()%>

+

Last: <%=idToken.getFamilyName()%>

Customer Listing

<% java.util.List list = null; diff --git a/examples/demo-template/third-party/src/main/webapp/pull_data.jsp b/examples/demo-template/third-party/src/main/webapp/pull_data.jsp index 6ed0478331..9f102b48c4 100755 --- a/examples/demo-template/third-party/src/main/webapp/pull_data.jsp +++ b/examples/demo-template/third-party/src/main/webapp/pull_data.jsp @@ -2,7 +2,6 @@ <%@ page import="org.keycloak.representations.AccessTokenResponse" %> <%@ page import="org.keycloak.representations.IDToken" %> <%@ page import="org.keycloak.servlet.ServletOAuthClient" %> -<%@ page import="org.keycloak.representations.UserClaimSet" %> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ page session="false" %> @@ -17,16 +16,15 @@ AccessTokenResponse tokenResponse = ProductDatabaseClient.getTokenResponse(request); if (tokenResponse.getIdToken() != null) { IDToken idToken = ServletOAuthClient.extractIdToken(tokenResponse.getIdToken()); - UserClaimSet claimSet = idToken.getUserClaimSet(); out.println("

Change client claims in admin console to view personal info of user

"); - if (claimSet.getPreferredUsername() != null) { - out.println("

Username: " + claimSet.getPreferredUsername() + "

"); + if (idToken.getPreferredUsername() != null) { + out.println("

Username: " + idToken.getPreferredUsername() + "

"); } - if (claimSet.getName() != null) { - out.println("

Full Name: " + claimSet.getName() + "

"); + if (idToken.getName() != null) { + out.println("

Full Name: " + idToken.getName() + "

"); } - if (claimSet.getEmail() != null) { - out.println("

Email: " + claimSet.getEmail() + "

"); + if (idToken.getEmail() != null) { + out.println("

Email: " + idToken.getEmail() + "

"); } } list = ProductDatabaseClient.getProducts(request, tokenResponse.getToken()); diff --git a/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/boundary/ProtectedServlet.java b/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/boundary/ProtectedServlet.java old mode 100644 new mode 100755 index ad41327cea..ff3237b1b9 --- a/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/boundary/ProtectedServlet.java +++ b/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/boundary/ProtectedServlet.java @@ -55,7 +55,7 @@ public class ProtectedServlet extends HttpServlet { writer.write(principal.getKeycloakSecurityContext().getIdToken().getIssuer()); writer.write("
User: "); - writer.write(principal.getKeycloakSecurityContext().getIdToken().getUserClaimSet().getPreferredUsername()); + writer.write(principal.getKeycloakSecurityContext().getIdToken().getPreferredUsername()); writer.write(String.format("
Logout", realm)); } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java index 371696be70..28b3d7dd1d 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java @@ -4,7 +4,6 @@ import org.jboss.logging.Logger; import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakSecurityContext; import org.keycloak.representations.AccessToken; -import org.keycloak.representations.UserClaimSet; import org.keycloak.util.UriUtils; import java.util.Collections; @@ -78,22 +77,21 @@ public class AdapterUtils { String attr = "sub"; if (deployment.getPrincipalAttribute() != null) attr = deployment.getPrincipalAttribute(); String name = null; - UserClaimSet claimSet = token.getUserClaimSet(); if ("sub".equals(attr)) { name = token.getSubject(); } else if ("email".equals(attr)) { - name = claimSet.getEmail(); + name = token.getEmail(); } else if ("preferred_username".equals(attr)) { - name = claimSet.getPreferredUsername(); + name = token.getPreferredUsername(); } else if ("name".equals(attr)) { - name = claimSet.getName(); + name = token.getName(); } else if ("given_name".equals(attr)) { - name = claimSet.getGivenName(); + name = token.getGivenName(); } else if ("family_name".equals(attr)) { - name = claimSet.getFamilyName(); + name = token.getFamilyName(); } else if ("nickname".equals(attr)) { - name = claimSet.getNickName(); + name = token.getNickName(); } if (name == null) name = token.getSubject(); return name; diff --git a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java index add140431e..58186dc298 100755 --- a/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java +++ b/proxy/proxy-server/src/main/java/org/keycloak/proxy/ConstraintAuthorizationHandler.java @@ -4,7 +4,6 @@ import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.util.HttpString; import org.keycloak.adapters.undertow.KeycloakUndertowAccount; -import org.keycloak.representations.UserClaimSet; import org.keycloak.representations.IDToken; /** @@ -65,16 +64,14 @@ public class ConstraintAuthorizationHandler implements HttpHandler { exchange.getRequestHeaders().put(KEYCLOAK_SUBJECT, idToken.getSubject()); } - UserClaimSet claimSet = idToken.getUserClaimSet(); - - if (claimSet.getPreferredUsername() != null) { - exchange.getRequestHeaders().put(KEYCLOAK_USERNAME, claimSet.getPreferredUsername()); + if (idToken.getPreferredUsername() != null) { + exchange.getRequestHeaders().put(KEYCLOAK_USERNAME, idToken.getPreferredUsername()); } - if (claimSet.getEmail() != null) { - exchange.getRequestHeaders().put(KEYCLOAK_EMAIL, claimSet.getEmail()); + if (idToken.getEmail() != null) { + exchange.getRequestHeaders().put(KEYCLOAK_EMAIL, idToken.getEmail()); } - if (claimSet.getName() != null) { - exchange.getRequestHeaders().put(KEYCLOAK_NAME, claimSet.getName()); + if (idToken.getName() != null) { + exchange.getRequestHeaders().put(KEYCLOAK_NAME, idToken.getName()); } if (sendAccessToken) { exchange.getRequestHeaders().put(KEYCLOAK_ACCESS_TOKEN, account.getKeycloakSecurityContext().getTokenString()); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java index 2d58fea193..1fc1277fb1 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java @@ -7,7 +7,6 @@ import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.protocol.AbstractLoginProtocolFactory; import org.keycloak.protocol.LoginProtocol; -import org.keycloak.protocol.ProtocolMapperUtils; import org.keycloak.protocol.oidc.mappers.OIDCAddressMapper; import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; import org.keycloak.protocol.oidc.mappers.OIDCFullNameMapper; @@ -88,16 +87,7 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory { builtins.add(fullName); defaultBuiltins.add(fullName); - ProtocolMapperModel address = new ProtocolMapperModel(); - address.setName("address"); - address.setProtocolMapper(OIDCAddressMapper.PROVIDER_ID); - address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); - address.setConsentRequired(true); - address.setConsentText("address"); - config = new HashMap(); - config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true"); - config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true"); - address.setConfig(config); + ProtocolMapperModel address = OIDCAddressMapper.createAddressMapper(); builtins.add(address); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAddressMapper.java index da7a25893a..235f2abfd7 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAddressMapper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAddressMapper.java @@ -5,12 +5,15 @@ 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.representations.AccessToken; +import org.keycloak.representations.AddressClaimSet; import org.keycloak.representations.IDToken; -import org.keycloak.representations.UserClaimSet; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Set the 'name' claim to be first + last name. @@ -42,6 +45,35 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID public static final String PROVIDER_ID = "oidc-address-mapper"; + public static ProtocolMapperModel createAddressMapper() { + Map 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(); + config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true"); + config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true"); + address.setConfig(config); + return address; + } + public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) { + Map 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(); + config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken)); + config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken)); + address.setConfig(config); + return address; + } + public List getConfigProperties() { return configProperties; @@ -84,7 +116,7 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID protected void setClaim(IDToken token, UserSessionModel userSession) { UserModel user = userSession.getUser(); - UserClaimSet.AddressClaimSet addressSet = new UserClaimSet.AddressClaimSet(); + AddressClaimSet addressSet = new AddressClaimSet(); addressSet.setStreetAddress(user.getAttribute("street")); addressSet.setLocality(user.getAttribute("locality")); addressSet.setRegion(user.getAttribute("region")); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenantServlet.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenantServlet.java old mode 100644 new mode 100755 index 1501f048e6..e464a7b9b6 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenantServlet.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenantServlet.java @@ -38,7 +38,7 @@ public class MultiTenantServlet extends HttpServlet { KeycloakSecurityContext context = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName()); pw.print("Username: "); - pw.println(context.getIdToken().getUserClaimSet().getPreferredUsername()); + pw.println(context.getIdToken().getPreferredUsername()); pw.print("
Realm: "); pw.println(context.getRealm()); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java index d03cb596eb..6fca683cb3 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java @@ -26,18 +26,24 @@ import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; +import org.keycloak.VerificationException; import org.keycloak.enums.SslRequired; import org.keycloak.events.Details; import org.keycloak.events.Errors; import org.keycloak.events.Event; +import org.keycloak.jose.jws.JWSInput; import org.keycloak.models.ApplicationModel; import org.keycloak.models.ClientModel; import org.keycloak.models.KeycloakSession; +import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.UserModel; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; +import org.keycloak.protocol.oidc.mappers.OIDCAddressMapper; +import org.keycloak.protocol.oidc.mappers.OIDCUserAttributeMapper; import org.keycloak.representations.AccessToken; +import org.keycloak.representations.IDToken; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.OAuthClient; @@ -58,6 +64,7 @@ import javax.ws.rs.core.GenericType; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; +import java.io.IOException; import java.net.URI; import java.util.HashMap; @@ -570,6 +577,84 @@ public class AccessTokenTest { } + @Test + public void testTokenMapping() throws Exception { + Client client = ClientBuilder.newClient(); + UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT); + URI grantUri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("test"); + WebTarget grantTarget = client.target(grantUri); + { + KeycloakSession session = keycloakRule.startSession(); + RealmModel realm = session.realms().getRealmByName("test"); + UserModel user = session.users().getUserByUsername("test-user@localhost", realm); + user.setAttribute("street", "5 Yawkey Way"); + user.setAttribute("locality", "Boston"); + user.setAttribute("region", "MA"); + user.setAttribute("postal_code", "02115"); + user.setAttribute("country", "USA"); + user.setAttribute("phone", "617-777-6666"); + ApplicationModel app = realm.getApplicationByName("test-app"); + ProtocolMapperModel mapper = OIDCAddressMapper.createAddressMapper(true, true); + app.addProtocolMapper(mapper); + app.addProtocolMapper(OIDCUserAttributeMapper.createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true)); + session.getTransaction().commit(); + session.close(); + } + + { + Response response = executeGrantAccessTokenRequest(grantTarget); + Assert.assertEquals(200, response.getStatus()); + org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class); + IDToken idToken = getIdToken(tokenResponse); + Assert.assertNotNull(idToken.getAddress()); + Assert.assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way"); + Assert.assertEquals(idToken.getAddress().getLocality(), "Boston"); + Assert.assertEquals(idToken.getAddress().getRegion(), "MA"); + Assert.assertEquals(idToken.getAddress().getPostalCode(), "02115"); + Assert.assertEquals(idToken.getAddress().getCountry(), "USA"); + Assert.assertNotNull(idToken.getOtherClaims().get("home_phone")); + //Assert.assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone")); + + AccessToken accessToken = getAccessToken(tokenResponse); + Assert.assertNotNull(accessToken.getAddress()); + Assert.assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way"); + Assert.assertEquals(accessToken.getAddress().getLocality(), "Boston"); + Assert.assertEquals(accessToken.getAddress().getRegion(), "MA"); + Assert.assertEquals(accessToken.getAddress().getPostalCode(), "02115"); + Assert.assertEquals(accessToken.getAddress().getCountry(), "USA"); + Assert.assertNotNull(accessToken.getOtherClaims().get("home_phone")); + Assert.assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone")); + + + response.close(); + } + client.close(); + events.clear(); + + } + + private IDToken getIdToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException { + JWSInput input = new JWSInput(tokenResponse.getIdToken()); + IDToken idToken = null; + try { + idToken = input.readJsonContent(IDToken.class); + } catch (IOException e) { + throw new VerificationException(); + } + return idToken; + } + + private AccessToken getAccessToken(org.keycloak.representations.AccessTokenResponse tokenResponse) throws VerificationException { + JWSInput input = new JWSInput(tokenResponse.getIdToken()); + AccessToken idToken = null; + try { + idToken = input.readJsonContent(AccessToken.class); + } catch (IOException e) { + throw new VerificationException(); + } + return idToken; + } + protected Response executeGrantAccessTokenRequest(WebTarget grantTarget) { String header = BasicAuthHelper.createHeader("test-app", "password"); Form form = new Form();