keycloak-developers

fix other claims in IDToken

3/4/2015 10:27:06 PM

Details

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 0000000..4b47b8f
--- /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 <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @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 fa58c9e..523d1f1 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<String, Object> otherClaims = new HashMap<String, Object>();
 
@@ -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 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 setUserClaimSet(UserClaimSet userClaimSet) {
-        this.userClaimSet = userClaimSet;
+    public void setClaimsLocales(String claimsLocales) {
+        this.claimsLocales = claimsLocales;
     }
 
     /**
@@ -65,7 +272,7 @@ public class IDToken extends JsonWebToken {
     }
 
     @JsonAnySetter
-    public void setOtherClaims(Map<String, Object> 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/UserInfo.java b/core/src/main/java/org/keycloak/representations/UserInfo.java
old mode 100644
new mode 100755
index 3112981..d9542fa
--- 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 7929495..1f51c21 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<String, String> nested = new HashMap<String, String>();
         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<String, String>)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 e5a332d..268cddd 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 2eb5e66..04a54bb 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" %>
 <html>
@@ -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();
 %>
 <p>Goto: <a href="/product-portal">products</a> | <a href="<%=logoutUri%>">logout</a> | <a
         href="<%=acctUri%>">manage acct</a></p>
 Servlet User Principal <b><%=request.getUserPrincipal().getName()%>
 </b> made this request.
 <p><b>Caller IDToken values</b> (<i>You can specify what is returned in IDToken in the customer-portal claims page in the admin console</i>:</p>
-<p>Username: <%=claims.getPreferredUsername()%></p>
-<p>Email: <%=claims.getEmail()%></p>
-<p>Full Name: <%=claims.getName()%></p>
-<p>First: <%=claims.getGivenName()%></p>
-<p>Last: <%=claims.getFamilyName()%></p>
+<p>Username: <%=idToken.getPreferredUsername()%></p>
+<p>Email: <%=idToken.getEmail()%></p>
+<p>Full Name: <%=idToken.getName()%></p>
+<p>First: <%=idToken.getGivenName()%></p>
+<p>Last: <%=idToken.getFamilyName()%></p>
 <h2>Customer Listing</h2>
 <%
     java.util.List<String> 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 6ed0478..9f102b4 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("<p><i>Change client claims in admin console to view personal info of user</i></p>");
-            if (claimSet.getPreferredUsername() != null) {
-                out.println("<p>Username: " + claimSet.getPreferredUsername() + "</p>");
+            if (idToken.getPreferredUsername() != null) {
+                out.println("<p>Username: " + idToken.getPreferredUsername() + "</p>");
             }
-            if (claimSet.getName() != null) {
-                out.println("<p>Full Name: " + claimSet.getName() + "</p>");
+            if (idToken.getName() != null) {
+                out.println("<p>Full Name: " + idToken.getName() + "</p>");
             }
-            if (claimSet.getEmail() != null) {
-                out.println("<p>Email: " + claimSet.getEmail() + "</p>");
+            if (idToken.getEmail() != null) {
+                out.println("<p>Email: " + idToken.getEmail() + "</p>");
             }
         }
         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 ad41327..ff3237b
--- 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("<br/>User: ");
-        writer.write(principal.getKeycloakSecurityContext().getIdToken().getUserClaimSet().getPreferredUsername());
+        writer.write(principal.getKeycloakSecurityContext().getIdToken().getPreferredUsername());
 
         writer.write(String.format("<br/><a href=\"/multitenant/%s/logout\">Logout</a>", 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 371696b..28b3d7d 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 add1404..58186dc 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/mappers/OIDCAddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAddressMapper.java
index da7a258..235f2ab 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<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;
+    }
+    public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) {
+        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, Boolean.toString(idToken));
+        config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken));
+        address.setConfig(config);
+        return address;
+    }
+
 
     public List<ConfigProperty> 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/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
index 2d58fea..1fc1277 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<String, String>();
-        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/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 1501f04..e464a7b
--- 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("<br/>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 d03cb59..6fca683 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();