keycloak-aplcache

fixes

3/2/2015 11:39:43 PM

Details

diff --git a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
index 78e13bd..1e510f8 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ProtocolMapperTypeRepresentation.java
@@ -16,6 +16,8 @@ public class ProtocolMapperTypeRepresentation {
         protected String name;
         protected String label;
         protected String helpText;
+        protected String type;
+        protected String defaultValue;
 
         public String getName() {
             return name;
@@ -33,6 +35,22 @@ public class ProtocolMapperTypeRepresentation {
             this.label = label;
         }
 
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getDefaultValue() {
+            return defaultValue;
+        }
+
+        public void setDefaultValue(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
         public String getHelpText() {
             return helpText;
         }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 2bf61e2..f24a094 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -457,12 +457,6 @@ public class RepresentationToModel {
             applicationModel.updateDefaultRoles(resourceRep.getDefaultRoles());
         }
 
-        if (resourceRep.getClaims() != null) {
-            setClaims(applicationModel, resourceRep.getClaims());
-        } else {
-            applicationModel.setAllowedClaimsMask(ClaimMask.ALL);
-        }
-
         if (resourceRep.getProtocolMappers() != null) {
             Set<String> ids = new HashSet<String>();
             for (ClientProtocolMappingRepresentation map : resourceRep.getProtocolMappers()) {
@@ -524,10 +518,6 @@ public class RepresentationToModel {
             }
         }
 
-        if (rep.getClaims() != null) {
-            setClaims(resource, rep.getClaims());
-        }
-
         updateClientIdentityProvides(rep.getIdentityProviders(), resource);
     }
 
@@ -633,10 +623,6 @@ public class RepresentationToModel {
             model.setWebOrigins(new HashSet<String>(webOrigins));
         }
 
-        if (rep.getClaims() != null) {
-            setClaims(model, rep.getClaims());
-        }
-
         if (rep.getNotBefore() != null) {
             model.setNotBefore(rep.getNotBefore());
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
index e2c479f..eebda6f 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAccessTokenMapper.java
@@ -12,6 +12,6 @@ import org.keycloak.representations.AccessToken;
  */
 public interface OIDCAccessTokenMapper {
 
-    AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                               UserSessionModel userSession, ClientSessionModel clientSession);
+    AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                     UserSessionModel userSession, ClientSessionModel clientSession);
 }
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 9b3adab..da7a258 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
@@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 import org.keycloak.representations.UserClaimSet;
 
 import java.util.ArrayList;
@@ -17,12 +18,26 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
 
     private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
 
     static {
-
+        ConfigProperty property;
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
+        configProperties.add(property);
     }
 
     public static final String PROVIDER_ID = "oidc-address-mapper";
@@ -53,8 +68,21 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID
     }
 
     @Override
-    public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
+        setClaim(token, userSession);
+        return token;
+    }
+
+    @Override
+    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
+        setClaim(token, userSession);
+        return token;
+    }
+
+    protected void setClaim(IDToken token, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         UserClaimSet.AddressClaimSet addressSet = new UserClaimSet.AddressClaimSet();
         addressSet.setStreetAddress(user.getAttribute("street"));
@@ -63,7 +91,6 @@ public class OIDCAddressMapper extends AbstractOIDCProtocolMapper implements OID
         addressSet.setPostalCode(user.getAttribute("postal_code"));
         addressSet.setCountry(user.getAttribute("country"));
         token.getOtherClaims().put("address", addressSet);
-        return token;
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
index a6c98be..552e471 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
@@ -5,6 +5,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -16,6 +17,12 @@ import java.util.Map;
 public class OIDCAttributeMapperHelper {
     public static final String TOKEN_CLAIM_NAME = "Token Claim Name";
     public static final String JSON_TYPE = "Claim JSON Type";
+    public static final String INCLUDE_IN_ACCESS_TOKEN = "access.token.claim";
+    public static final String INCLUDE_IN_ACCESS_TOKEN_LABEL = "Add to access token";
+    public static final String INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT = "Should the claim be added to the access token?";
+    public static final String INCLUDE_IN_ID_TOKEN = "id.token.claim";
+    public static final String INCLUDE_IN_ID_TOKEN_LABEL = "Add to ID token";
+    public static final String INCLUDE_IN_ID_TOKEN_HELP_TEXT = "Should the claim be added to the ID token?";
 
     public static Object mapAttributeValue(ProtocolMapperModel mappingModel, Object attributeValue) {
         if (attributeValue == null) return null;
@@ -40,7 +47,7 @@ public class OIDCAttributeMapperHelper {
         return attributeValue;
     }
 
-    public static void mapClaim(AccessToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
+    public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) {
         if (attributeValue == null) return;
         attributeValue = mapAttributeValue(mappingModel, attributeValue);
         String protocolClaim = mappingModel.getConfig().get(TOKEN_CLAIM_NAME);
@@ -65,6 +72,7 @@ public class OIDCAttributeMapperHelper {
                                   String tokenClaimName, String claimType,
                                   boolean consentRequired, String consentText,
                                   boolean appliedByDefault,
+                                  boolean accessToken, boolean idToken,
                                   String mapperId) {
         ProtocolMapperModel mapper = realm.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, name);
         if (mapper != null) return;
@@ -79,7 +87,17 @@ public class OIDCAttributeMapperHelper {
         config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
         config.put(TOKEN_CLAIM_NAME, tokenClaimName);
         config.put(JSON_TYPE, claimType);
+        if (accessToken) config.put(INCLUDE_IN_ACCESS_TOKEN, "true");
+        if (idToken) config.put(INCLUDE_IN_ID_TOKEN, "true");
         mapper.setConfig(config);
         realm.addProtocolMapper(mapper);
     }
+
+    public static boolean includeInIDToken(ProtocolMapperModel mappingModel) {
+        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ID_TOKEN));
+    }
+
+    public static boolean includeInAccessToken(ProtocolMapperModel mappingModel) {
+        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
+    }
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCFullNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCFullNameMapper.java
index 169494a..f91abe5 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCFullNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCFullNameMapper.java
@@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -16,11 +17,26 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
 
     private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
 
     static {
+        ConfigProperty property;
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
+        configProperties.add(property);
 
     }
 
@@ -52,13 +68,24 @@ public class OIDCFullNameMapper extends AbstractOIDCProtocolMapper implements OI
     }
 
     @Override
-    public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
+        setClaim(token, userSession);
+        return token;
+    }
+
+    protected void setClaim(IDToken token, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         String first = user.getFirstName() == null ? "" : user.getFirstName() + " ";
         String last = user.getLastName() == null ? "" : user.getLastName();
         token.getOtherClaims().put("name", first + last);
-        return token;
     }
 
+    @Override
+    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
+        setClaim(token, userSession);
+        return token;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
new file mode 100755
index 0000000..932b431
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCIDTokenMapper.java
@@ -0,0 +1,18 @@
+package org.keycloak.protocol.oidc.mappers;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface OIDCIDTokenMapper {
+
+    IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                               UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserAttributeMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserAttributeMapper.java
index 3586372..98045ba 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserAttributeMapper.java
@@ -8,6 +8,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -20,7 +21,7 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
 
     private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
 
@@ -30,12 +31,35 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
         property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
         property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
         property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
+        property.setType(ConfigProperty.STRING_TYPE);
         configProperties.add(property);
         property = new ConfigProperty();
         property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
         property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
+        property.setType(ConfigProperty.STRING_TYPE);
         property.setHelpText("Name of the claim to insert into the token.  This can be a fully qualified name like 'address.street'.  In this case, a nested json object will be created.");
         configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setType(ConfigProperty.STRING_TYPE);
+        property.setDefaultValue(ConfigProperty.STRING_TYPE);
+        property.setHelpText("JSON type that should be used to populate the json claim in the token.  long, int, boolean, and String are valid values.");
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
+        configProperties.add(property);
 
     }
 
@@ -67,13 +91,26 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
     }
 
     @Override
-    public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
+
+        setClaim(token, mappingModel, userSession);
+        return token;
+    }
+
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
         String attributeValue = user.getAttribute(attributeName);
-        if (attributeValue == null) return token;
+        if (attributeValue == null) return;
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue);
+    }
+
+    @Override
+    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
+        setClaim(token, mappingModel, userSession);
         return token;
     }
 
@@ -81,11 +118,13 @@ public class OIDCUserAttributeMapper extends AbstractOIDCProtocolMapper implemen
                                       String userAttribute,
                                       String tokenClaimName, String claimType,
                                       boolean consentRequired, String consentText,
-                                      boolean appliedByDefault) {
+                                      boolean appliedByDefault,
+                                      boolean accessToken, boolean idToken) {
         OIDCAttributeMapperHelper.addClaimMapper(realm, name, userAttribute,
                 tokenClaimName, claimType,
                 consentRequired, consentText,
-                appliedByDefault, PROVIDER_ID);
+                appliedByDefault, accessToken, idToken,
+                PROVIDER_ID);
     }
 
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java
index 5e97f6d..5efa6c6 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCUserModelMapper.java
@@ -8,6 +8,7 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -20,7 +21,7 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
+public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
     private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
 
     static {
@@ -28,14 +29,43 @@ public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements O
         property = new ConfigProperty();
         property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
         property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
+        property.setType(ConfigProperty.STRING_TYPE);
         property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
         configProperties.add(property);
         property = new ConfigProperty();
         property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
         property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
+        property.setType(ConfigProperty.STRING_TYPE);
         property.setHelpText("Name of the claim to insert into the token.  This can be a fully qualified name like 'address.street'.  In this case, a nested json object will be created.");
         configProperties.add(property);
-
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setType(ConfigProperty.STRING_TYPE);
+        property.setDefaultValue(ConfigProperty.STRING_TYPE);
+        property.setHelpText("JSON type that should be used to populate the json claim in the token.  long, int, boolean, and String are valid values.");
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText("JSON type that should be used to populate the json claim in the token.  long, int, boolean, and String are valid values.");
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
+        configProperties.add(property);
+        property = new ConfigProperty();
+        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
+        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
+        property.setType(ConfigProperty.BOOLEAN_TYPE);
+        property.setDefaultValue("true");
+        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
+        configProperties.add(property);
     }
 
     public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
@@ -66,25 +96,40 @@ public class OIDCUserModelMapper extends AbstractOIDCProtocolMapper implements O
     }
 
     @Override
-    public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
+        setClaim(token, mappingModel, userSession);
+
+        return token;
+    }
+
+    @Override
+    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
+        setClaim(token, mappingModel, userSession);
+
+        return token;
+    }
+
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
         String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, propertyValue);
-
-        return token;
     }
 
     public static void addClaimMapper(RealmModel realm, String name,
                                       String userAttribute,
                                       String tokenClaimName, String claimType,
                                       boolean consentRequired, String consentText,
-                                      boolean appliedByDefault) {
+                                      boolean appliedByDefault,
+                                      boolean accessToken, boolean idToken) {
         OIDCAttributeMapperHelper.addClaimMapper(realm, name, userAttribute,
                 tokenClaimName, claimType,
                 consentRequired, consentText,
-                appliedByDefault, PROVIDER_ID);
+                appliedByDefault, accessToken, idToken,
+                PROVIDER_ID);
     }
 
 
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 a53a759..8d3a636 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -29,27 +29,32 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
                 "username",
                 "preferred_username", "String",
                 true, "username",
-                true);
+                true,
+                true, true);
         OIDCUserModelMapper.addClaimMapper(realm, "email",
                 "email",
                 "email", "String",
                 true, "email",
-                true);
+                true,
+                true, true);
         OIDCUserModelMapper.addClaimMapper(realm, "given name",
                 "firstName",
                 "given_name", "String",
                 true, "given name",
-                true);
+                true,
+                true, true);
         OIDCUserModelMapper.addClaimMapper(realm, "family name",
                 "lastName",
                 "family_name", "String",
                 true, "family name",
-                true);
+                true,
+                true, true);
         OIDCUserModelMapper.addClaimMapper(realm, "email verified",
                 "emailVerified",
                 "email_verified", "boolean",
                 false, null,
-                false);
+                false,
+                true, true);
 
         ProtocolMapperModel fullName = new ProtocolMapperModel();
         if (realm.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "full name") == null) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index 8e48aeb..55a78da 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -9,7 +9,6 @@ import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
 import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClaimMask;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -25,7 +24,6 @@ import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.UserClaimSet;
 import org.keycloak.representations.IDToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.services.managers.AuthenticationManager;
@@ -244,7 +242,7 @@ public class TokenManager {
 
             ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
             if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue;
-            token = ((OIDCAccessTokenMapper)mapper).transformToken(token, mapping, session, userSession, clientSession);
+            token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
 
 
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
index 0829d67..c96b9f1 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
@@ -1,154 +1,154 @@
-/*
- * 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.protocol.oidc;
-
-import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.jboss.resteasy.spi.HttpResponse;
-import org.jboss.resteasy.spi.UnauthorizedException;
-import org.keycloak.ClientConnection;
-import org.keycloak.events.Details;
-import org.keycloak.events.EventBuilder;
-import org.keycloak.events.EventType;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.UserClaimSet;
-import org.keycloak.services.managers.AppAuthManager;
-import org.keycloak.services.managers.EventsManager;
-import org.keycloak.services.resources.Cors;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.OPTIONS;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author pedroigor
- */
-public class UserInfoService {
-
-    @Context
-    private HttpRequest request;
-
-    @Context
-    private HttpResponse response;
-
-    @Context
-    private KeycloakSession session;
-
-    @Context
-    private ClientConnection clientConnection;
-
-    private final TokenManager tokenManager;
-    private final AppAuthManager appAuthManager;
-    private final OIDCLoginProtocolService openIdConnectService;
-    private final RealmModel realmModel;
-
-    public UserInfoService(OIDCLoginProtocolService openIDConnectService) {
-        this.realmModel = openIDConnectService.getRealm();
-
-        if (this.realmModel == null) {
-            throw new RuntimeException("Null realm.");
-        }
-
-        this.tokenManager = openIDConnectService.getTokenManager();
-
-        if (this.tokenManager == null) {
-            throw new RuntimeException("Null token manager.");
-        }
-
-        this.openIdConnectService = openIDConnectService;
-        this.appAuthManager = new AppAuthManager();
-    }
-
-    @Path("/")
-    @OPTIONS
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoPreflight() {
-        return Cors.add(this.request, Response.ok()).auth().preflight().build();
-    }
-
-    @Path("/")
-    @GET
-    @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoGet(@Context final HttpHeaders headers) {
-        String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
-        return issueUserInfo(accessToken);
-    }
-
-    @Path("/")
-    @POST
-    @NoCache
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
-        return issueUserInfo(accessToken);
-    }
-
-    private Response issueUserInfo(String token) {
-        try {
-            EventBuilder event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder()
-                    .event(EventType.USER_INFO_REQUEST)
-                    .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
-
-            Response validationResponse = this.openIdConnectService.validateAccessToken(token);
-
-            if (!AccessToken.class.isInstance(validationResponse.getEntity())) {
-                event.error(EventType.USER_INFO_REQUEST.name());
-                return Response.fromResponse(validationResponse).status(Status.FORBIDDEN).build();
-            }
-
-            AccessToken accessToken = (AccessToken) validationResponse.getEntity();
-            UserSessionModel userSession = session.sessions().getUserSession(realmModel, accessToken.getSessionState());
-            ClientModel clientModel = realmModel.findClient(accessToken.getIssuedFor());
-            UserModel userModel = userSession.getUser();
-            AccessToken userInfo = new AccessToken();
-            this.tokenManager.transformToken(session, userInfo, realmModel, clientModel, userModel, userSession, null);
-
-            event
-                .detail(Details.USERNAME, userModel.getUsername())
-                .client(clientModel)
-                .session(userSession)
-                .user(userModel)
-                .success();
-
-            Map<String, Object> claims = new HashMap<String, Object>();
-            claims.putAll(userInfo.getOtherClaims());
-            claims.put("sub", userModel.getId());
-            return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(accessToken).build();
-        } catch (Exception e) {
-            throw new UnauthorizedException("Could not retrieve user info.", e);
-        }
-    }
-
-}
+/*
+ * 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.protocol.oidc;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.HttpResponse;
+import org.jboss.resteasy.spi.UnauthorizedException;
+import org.keycloak.ClientConnection;
+import org.keycloak.events.Details;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.UserClaimSet;
+import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.EventsManager;
+import org.keycloak.services.resources.Cors;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author pedroigor
+ */
+public class UserInfoService {
+
+    @Context
+    private HttpRequest request;
+
+    @Context
+    private HttpResponse response;
+
+    @Context
+    private KeycloakSession session;
+
+    @Context
+    private ClientConnection clientConnection;
+
+    private final TokenManager tokenManager;
+    private final AppAuthManager appAuthManager;
+    private final OIDCLoginProtocolService openIdConnectService;
+    private final RealmModel realmModel;
+
+    public UserInfoService(OIDCLoginProtocolService openIDConnectService) {
+        this.realmModel = openIDConnectService.getRealm();
+
+        if (this.realmModel == null) {
+            throw new RuntimeException("Null realm.");
+        }
+
+        this.tokenManager = openIDConnectService.getTokenManager();
+
+        if (this.tokenManager == null) {
+            throw new RuntimeException("Null token manager.");
+        }
+
+        this.openIdConnectService = openIDConnectService;
+        this.appAuthManager = new AppAuthManager();
+    }
+
+    @Path("/")
+    @OPTIONS
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoPreflight() {
+        return Cors.add(this.request, Response.ok()).auth().preflight().build();
+    }
+
+    @Path("/")
+    @GET
+    @NoCache
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoGet(@Context final HttpHeaders headers) {
+        String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
+        return issueUserInfo(accessToken);
+    }
+
+    @Path("/")
+    @POST
+    @NoCache
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response issueUserInfoPost(@FormParam("access_token") String accessToken) {
+        return issueUserInfo(accessToken);
+    }
+
+    private Response issueUserInfo(String token) {
+        try {
+            EventBuilder event = new EventsManager(this.realmModel, this.session, this.clientConnection).createEventBuilder()
+                    .event(EventType.USER_INFO_REQUEST)
+                    .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
+
+            Response validationResponse = this.openIdConnectService.validateAccessToken(token);
+
+            if (!AccessToken.class.isInstance(validationResponse.getEntity())) {
+                event.error(EventType.USER_INFO_REQUEST.name());
+                return Response.fromResponse(validationResponse).status(Status.FORBIDDEN).build();
+            }
+
+            AccessToken accessToken = (AccessToken) validationResponse.getEntity();
+            UserSessionModel userSession = session.sessions().getUserSession(realmModel, accessToken.getSessionState());
+            ClientModel clientModel = realmModel.findClient(accessToken.getIssuedFor());
+            UserModel userModel = userSession.getUser();
+            AccessToken userInfo = new AccessToken();
+            this.tokenManager.transformToken(session, userInfo, realmModel, clientModel, userModel, userSession, null);
+
+            event
+                .detail(Details.USERNAME, userModel.getUsername())
+                .client(clientModel)
+                .session(userSession)
+                .user(userModel)
+                .success();
+
+            Map<String, Object> claims = new HashMap<String, Object>();
+            claims.putAll(userInfo.getOtherClaims());
+            claims.put("sub", userModel.getId());
+            return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(accessToken).build();
+        } catch (Exception e) {
+            throw new UnauthorizedException("Could not retrieve user info.", e);
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
index 2c3d230..ff6e105 100755
--- a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
@@ -16,9 +16,14 @@ public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper
     String getHelpText();
 
     public static class ConfigProperty {
+        public static final String BOOLEAN_TYPE="boolean";
+        public static final String STRING_TYPE="String";
+
         protected String name;
         protected String label;
         protected String helpText;
+        protected String type;
+        protected String defaultValue;
 
         public String getName() {
             return name;
@@ -36,6 +41,22 @@ public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper
             this.label = label;
         }
 
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+
+        public String getDefaultValue() {
+            return defaultValue;
+        }
+
+        public void setDefaultValue(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
         public String getHelpText() {
             return helpText;
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
index 6871e95..0c87093 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ServerInfoAdminResource.java
@@ -150,6 +150,8 @@ public class ServerInfoAdminResource {
                 ProtocolMapperTypeRepresentation.ConfigProperty propRep = new ProtocolMapperTypeRepresentation.ConfigProperty();
                 propRep.setName(prop.getName());
                 propRep.setLabel(prop.getLabel());
+                propRep.setType(prop.getType());
+                propRep.setDefaultValue(prop.getDefaultValue());
                 propRep.setHelpText(prop.getHelpText());
                 rep.getProperties().add(propRep);
             }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
index 68e3f13..100f9c1 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/AdminAPITest.java
@@ -214,10 +214,6 @@ public class AdminAPITest {
 
             Assert.assertEquals(set, storedSet);
         }
-
-        if (appRep.getClaims() != null) {
-            Assert.assertEquals(appRep.getClaims(), storedApp.getClaims());
-        }
     }
 
     protected void checkRealmRep(RealmRepresentation rep, RealmRepresentation storedRealm) {