keycloak-aplcache

changes

2/20/2015 12:22:49 PM

Changes

Details

diff --git a/connections/jpa/src/main/resources/META-INF/persistence.xml b/connections/jpa/src/main/resources/META-INF/persistence.xml
index 5f428ee..8609f07 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -19,7 +19,7 @@
         <class>org.keycloak.models.jpa.entities.ScopeMappingEntity</class>
         <class>org.keycloak.models.jpa.entities.IdentityProviderEntity</class>
         <class>org.keycloak.models.jpa.entities.ClaimTypeEntity</class>
-        <class>org.keycloak.models.jpa.entities.ProtocolClaimMappingEntity</class>
+        <class>org.keycloak.models.jpa.entities.ProtocolMapperEntity</class>
 
         <!-- JpaUserSessionProvider -->
         <class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
index 9434203..0de32d8 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
@@ -1,13 +1,14 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
     <changeSet author="psilva@redhat.com" id="1.2.0.Beta1">
-        <createTable tableName="PROTOCOL_CLAIM_MAPPING">
+        <createTable tableName="PROTOCOL_MAPPER">
             <column name="ID" type="VARCHAR(36)">
                 <constraints nullable="false"/>
             </column>
             <column name="PROTOCOL_CLAIM" type="VARCHAR(255)"/>
             <column name="PROTOCOL" type="VARCHAR(255)"/>
             <column name="SOURCE" type="VARCHAR(255)"/>
+            <column name="PROTOCOL_MAPPER_NAME" type="VARCHAR(255)"/>
             <column name="SOURCE_ATTRIBUTE" type="VARCHAR(255)"/>
             <column name="APPLIED_BY_DEFAULT" type="BOOLEAN(1)"/>
             <column name="REALM_ID" type="VARCHAR(36)"/>
@@ -63,7 +64,7 @@
                 <constraints nullable="false"/>
             </column>
         </createTable>
-        <createTable tableName="CLIENT_PROTOCOL_CLAIM_MAPPING">
+        <createTable tableName="CLIENT_PROTOCOL_MAPPER">
             <column name="CLIENT_ID" type="VARCHAR(36)">
                 <constraints nullable="false"/>
             </column>
@@ -75,19 +76,19 @@
             <column name="FRONTCHANNEL_LOGOUT" type="BOOLEAN" defaultValueBoolean="false"/>
         </addColumn>
         <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_CT" tableName="CLAIM_TYPE"/>
-        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_PCM" tableName="PROTOCOL_CLAIM_MAPPING"/>
+        <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_PCM" tableName="PROTOCOL_MAPPER"/>
         <addPrimaryKey columnNames="INTERNAL_ID" constraintName="CONSTRAINT_2B" tableName="IDENTITY_PROVIDER"/>
         <addPrimaryKey columnNames="IDENTITY_PROVIDER, USER_ID" constraintName="CONSTRAINT_40" tableName="FEDERATED_IDENTITY"/>
         <addPrimaryKey columnNames="IDENTITY_PROVIDER_ID, NAME" constraintName="CONSTRAINT_D" tableName="IDENTITY_PROVIDER_CONFIG"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER" constraintName="FK2B4EBC52AE5C3B34" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLAIM_TYPE" constraintName="FK_CT_REALM" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
-        <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="PROTOCOL_CLAIM_MAPPING" constraintName="FK_PCM_REALM" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
+        <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="PROTOCOL_MAPPER" constraintName="FK_PCM_REALM" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="REALM"/>
         <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="FEDERATED_IDENTITY" constraintName="FK404288B92EF007A6" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
         <addForeignKeyConstraint baseColumnNames="IDENTITY_PROVIDER_ID" baseTableName="IDENTITY_PROVIDER_CONFIG" constraintName="FKDC4897CF864C4E43" deferrable="false" initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
         <addForeignKeyConstraint baseColumnNames="INTERNAL_ID" baseTableName="CLIENT_ALLOWED_IDENTITY_PROVIDER" constraintName="FK_7CELWNIBJI49AVXSRTUF6XJ12" referencedColumnNames="INTERNAL_ID" referencedTableName="IDENTITY_PROVIDER"/>
         <addUniqueConstraint columnNames="INTERNAL_ID,CLIENT_ID" constraintName="UK_7CAELWNIBJI49AVXSRTUF6XJ12" tableName="CLIENT_ALLOWED_IDENTITY_PROVIDER"/>
-        <addForeignKeyConstraint baseColumnNames="MAPPING_ID" baseTableName="CLIENT_PROTOCOL_CLAIM_MAPPING" constraintName="FK_CPCM" referencedColumnNames="ID" referencedTableName="PROTOCOL_CLAIM_MAPPING"/>
-        <addUniqueConstraint columnNames="CLIENT_ID,MAPPING_ID" constraintName="UK_CPCM" tableName="CLIENT_PROTOCOL_CLAIM_MAPPING"/>
+        <addForeignKeyConstraint baseColumnNames="MAPPING_ID" baseTableName="CLIENT_PROTOCOL_MAPPER" constraintName="FK_CPCM" referencedColumnNames="ID" referencedTableName="PROTOCOL_MAPPER"/>
+        <addUniqueConstraint columnNames="CLIENT_ID,MAPPING_ID" constraintName="UK_CPCM" tableName="CLIENT_PROTOCOL_MAPPER"/>
         <addUniqueConstraint columnNames="PROVIDER_NONIMAL_ID" constraintName="UK_2DAELWNIBJI49AVXSRTUF6XJ33" tableName="IDENTITY_PROVIDER"/>
     </changeSet>
 </databaseChangeLog>
diff --git a/core/src/main/java/org/keycloak/representations/AccessToken.java b/core/src/main/java/org/keycloak/representations/AccessToken.java
index a9eaf3e..4d099ca 100755
--- a/core/src/main/java/org/keycloak/representations/AccessToken.java
+++ b/core/src/main/java/org/keycloak/representations/AccessToken.java
@@ -64,6 +64,9 @@ public class AccessToken extends IDToken {
         }
     }
 
+    @JsonProperty("client_session")
+    protected String clientSession;
+
     @JsonProperty("trusted-certs")
     protected Set<String> trustedCertificates;
 
@@ -117,12 +120,21 @@ public class AccessToken extends IDToken {
         return resourceAccess.get(resource);
     }
 
+    public String getClientSession() {
+        return clientSession;
+    }
+
     public Access addAccess(String service) {
         Access token = new Access();
         resourceAccess.put(service, token);
         return token;
     }
 
+    public AccessToken clientSession(String session) {
+        this.clientSession = session;
+        return this;
+    }
+
     @Override
     public AccessToken id(String id) {
         return (AccessToken) super.id(id);
diff --git a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
index 4ee9c8b..9b655dc 100755
--- a/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/RealmRepresentation.java
@@ -64,7 +64,7 @@ public class RealmRepresentation {
     protected List<String> eventsListeners;
     private List<IdentityProviderRepresentation> identityProviders;
     private List<ClaimTypeRepresentation> claimTypes;
-    private List<ProtocolClaimMappingRepresentation> protocolClaimMappings;
+    private List<ProtocolMapperRepresentation> protocolClaimMappings;
     private Boolean identityFederationEnabled;
 
     public String getId() {
@@ -492,11 +492,11 @@ public class RealmRepresentation {
         this.claimTypes = claimTypes;
     }
 
-    public List<ProtocolClaimMappingRepresentation> getProtocolClaimMappings() {
+    public List<ProtocolMapperRepresentation> getProtocolClaimMappings() {
         return protocolClaimMappings;
     }
 
-    public void setProtocolClaimMappings(List<ProtocolClaimMappingRepresentation> protocolClaimMappings) {
+    public void setProtocolClaimMappings(List<ProtocolMapperRepresentation> protocolClaimMappings) {
         this.protocolClaimMappings = protocolClaimMappings;
     }
 }
diff --git a/core/src/main/java/org/keycloak/representations/IDToken.java b/core/src/main/java/org/keycloak/representations/IDToken.java
index 784e409..fa58c9e 100755
--- a/core/src/main/java/org/keycloak/representations/IDToken.java
+++ b/core/src/main/java/org/keycloak/representations/IDToken.java
@@ -1,8 +1,13 @@
 package org.keycloak.representations;
 
+import org.codehaus.jackson.annotate.JsonAnyGetter;
+import org.codehaus.jackson.annotate.JsonAnySetter;
 import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.annotate.JsonUnwrapped;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
@@ -18,6 +23,8 @@ public class IDToken extends JsonWebToken {
     @JsonUnwrapped
     protected UserClaimSet userClaimSet = new UserClaimSet();
 
+    protected Map<String, Object> otherClaims = new HashMap<String, Object>();
+
     public String getNonce() {
         return nonce;
     }
@@ -34,6 +41,11 @@ public class IDToken extends JsonWebToken {
         this.sessionState = sessionState;
     }
 
+    /**
+     * Standardized OpenID Connect claims
+     *
+     * @return
+     */
     public UserClaimSet getUserClaimSet() {
         return this.userClaimSet;
     }
@@ -41,4 +53,19 @@ public class IDToken extends JsonWebToken {
     public void setUserClaimSet(UserClaimSet userClaimSet) {
         this.userClaimSet = userClaimSet;
     }
+
+    /**
+     * This is a map of any other claims and data that might be in the IDToken.  Could be custom claims set up by the auth server
+     *
+     * @return
+     */
+    @JsonAnyGetter
+    public Map<String, Object> getOtherClaims() {
+        return otherClaims;
+    }
+
+    @JsonAnySetter
+    public void setOtherClaims(Map<String, Object> otherClaims) {
+        this.otherClaims = otherClaims;
+    }
 }
diff --git a/core/src/main/java/org/keycloak/representations/RefreshToken.java b/core/src/main/java/org/keycloak/representations/RefreshToken.java
index b536a1c..25bf9a5 100755
--- a/core/src/main/java/org/keycloak/representations/RefreshToken.java
+++ b/core/src/main/java/org/keycloak/representations/RefreshToken.java
@@ -1,5 +1,7 @@
 package org.keycloak.representations;
 
+import org.codehaus.jackson.annotate.JsonProperty;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -8,7 +10,9 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class RefreshToken extends AccessToken {
-    public RefreshToken() {
+
+
+    private RefreshToken() {
         type("REFRESH");
     }
 
@@ -20,6 +24,7 @@ public class RefreshToken extends AccessToken {
      */
     public RefreshToken(AccessToken token) {
         this();
+        this.clientSession = token.getClientSession();
         this.issuer = token.issuer;
         this.subject = token.subject;
         this.issuedFor = token.issuedFor;
diff --git a/core/src/main/java/org/keycloak/util/JsonSerialization.java b/core/src/main/java/org/keycloak/util/JsonSerialization.java
index 49a4502..a1a93ba 100755
--- a/core/src/main/java/org/keycloak/util/JsonSerialization.java
+++ b/core/src/main/java/org/keycloak/util/JsonSerialization.java
@@ -30,6 +30,9 @@ public class JsonSerialization {
 
     }
 
+    public static String writeValueAsPrettyString(Object obj) throws IOException {
+        return prettyMapper.writeValueAsString(obj);
+    }
     public static String writeValueAsString(Object obj) throws IOException {
         return mapper.writeValueAsString(obj);
     }
diff --git a/core/src/test/java/org/keycloak/JsonParserTest.java b/core/src/test/java/org/keycloak/JsonParserTest.java
old mode 100644
new mode 100755
index 265b401..7929495
--- a/core/src/test/java/org/keycloak/JsonParserTest.java
+++ b/core/src/test/java/org/keycloak/JsonParserTest.java
@@ -2,9 +2,16 @@ package org.keycloak;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
 
+import org.codehaus.jackson.annotate.JsonAnyGetter;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.annotate.JsonUnwrapped;
 import org.junit.Assert;
 import org.junit.Test;
+import org.keycloak.representations.IDToken;
 import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.util.JsonSerialization;
 
@@ -14,6 +21,26 @@ import org.keycloak.util.JsonSerialization;
 public class JsonParserTest {
 
     @Test
+    public void testUnwrap() throws Exception {
+        // just experimenting with unwrapped and any properties
+        IDToken test = new IDToken();
+        test.getOtherClaims().put("phone_number", "978-666-0000");
+        test.getOtherClaims().put("email_verified", "true");
+        Map<String, String> nested = new HashMap<String, String>();
+        nested.put("foo", "bar");
+        test.getOtherClaims().put("nested", nested);
+        String json = JsonSerialization.writeValueAsPrettyString(test);
+        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("map: " + test.getOtherClaims().get("phone_number"));
+        Assert.assertNotNull(test.getUserClaimSet().getPhoneNumber());
+        Assert.assertNull(test.getOtherClaims().get("phone_number"));
+    }
+
+    @Test
     public void testParsingSystemProps() throws IOException {
         System.setProperty("my.host", "foo");
         System.setProperty("con.pool.size", "200");
diff --git a/model/api/src/main/java/org/keycloak/models/ClientModel.java b/model/api/src/main/java/org/keycloak/models/ClientModel.java
index 3e3c53d..243de4d 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -104,7 +104,7 @@ public interface ClientModel {
 
     boolean hasIdentityProvider(String providerId);
 
-    Set<ProtocolClaimMappingModel> getProtocolClaimMappings();
-    void addProtocolClaimMappings(Set<String> mappingIds);
-    void removeProtocolClaimMappings(Set<String> mappingIds);
+    Set<ProtocolMapperModel> getProtocolMappers();
+    void addProtocolMappers(Set<String> mapperIds);
+    void removeProtocolMappers(Set<String> mapperIds);
 }
diff --git a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
index e4324e3..7db0bac 100755
--- a/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -53,7 +53,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
     private List<UserFederationProviderEntity> userFederationProviders = new ArrayList<UserFederationProviderEntity>();
     private List<IdentityProviderEntity> identityProviders = new ArrayList<IdentityProviderEntity>();
     private List<ClaimTypeEntity> claimTypes = new ArrayList<ClaimTypeEntity>();
-    private List<ProtocolClaimMappingEntity> claimMappings = new ArrayList<ProtocolClaimMappingEntity>();
+    private List<ProtocolMapperEntity> claimMappings = new ArrayList<ProtocolMapperEntity>();
 
     private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
     private Map<String, String> smtpConfig = new HashMap<String, String>();
@@ -401,11 +401,11 @@ public class RealmEntity extends AbstractIdentifiableEntity {
         this.claimTypes = claimTypes;
     }
 
-    public List<ProtocolClaimMappingEntity> getClaimMappings() {
+    public List<ProtocolMapperEntity> getClaimMappings() {
         return claimMappings;
     }
 
-    public void setClaimMappings(List<ProtocolClaimMappingEntity> claimMappings) {
+    public void setClaimMappings(List<ProtocolMapperEntity> claimMappings) {
         this.claimMappings = claimMappings;
     }
 }
diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java
index 881f102..badc6bd 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -230,11 +230,11 @@ public interface RealmModel extends RoleContainerModel {
     ClaimTypeModel getClaimType(String name);
     void updateClaimType(ClaimTypeModel claimType);
 
-    Set<ProtocolClaimMappingModel> getProtocolClaimMappings();
-    ProtocolClaimMappingModel addProtocolClaimMapping(ProtocolClaimMappingModel model);
-    void removeProtocolClaimMapping(ProtocolClaimMappingModel mapping);
-    void updateProtocolClaimMapping(ProtocolClaimMappingModel mapping);
-    public ProtocolClaimMappingModel getProtocolClaimMappingById(String id);
+    Set<ProtocolMapperModel> getProtocolMappers();
+    ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model);
+    void removeProtocolMapper(ProtocolMapperModel mapping);
+    void updateProtocolMapper(ProtocolMapperModel mapping);
+    public ProtocolMapperModel getProtocolMapperById(String id);
 
 
 }
diff --git a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 6bff99e..5d0c582 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -8,7 +8,7 @@ import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.FederatedIdentityModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.OAuthClientModel;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
@@ -23,7 +23,7 @@ import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.FederatedIdentityRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.representations.idm.OAuthClientRepresentation;
-import org.keycloak.representations.idm.ProtocolClaimMappingRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
@@ -157,7 +157,7 @@ public class ModelToRepresentation {
             rep.getClaimTypes().add(toRepresentation(claimType));
         }
 
-        for (ProtocolClaimMappingModel mapping : realm.getProtocolClaimMappings()) {
+        for (ProtocolMapperModel mapping : realm.getProtocolMappers()) {
             rep.getProtocolClaimMappings().add(toRepresentation(mapping));
         }
 
@@ -265,9 +265,9 @@ public class ModelToRepresentation {
             rep.setAllowedIdentityProviders(applicationModel.getAllowedIdentityProviders());
         }
 
-        if (!applicationModel.getProtocolClaimMappings().isEmpty()) {
+        if (!applicationModel.getProtocolMappers().isEmpty()) {
             Set<String> mappings = new HashSet<String>();
-            for (ProtocolClaimMappingModel model : applicationModel.getProtocolClaimMappings()) mappings.add(model.getId());
+            for (ProtocolMapperModel model : applicationModel.getProtocolMappers()) mappings.add(model.getId());
             rep.setProtocolClaimMappings(mappings);
         }
 
@@ -300,9 +300,9 @@ public class ModelToRepresentation {
             rep.setAllowedIdentityProviders(model.getAllowedIdentityProviders());
         }
 
-        if (!model.getProtocolClaimMappings().isEmpty()) {
+        if (!model.getProtocolMappers().isEmpty()) {
             Set<String> mappings = new HashSet<String>();
-            for (ProtocolClaimMappingModel mappingMoel : model.getProtocolClaimMappings()) mappings.add(mappingMoel.getId());
+            for (ProtocolMapperModel mappingMoel : model.getProtocolMappers()) mappings.add(mappingMoel.getId());
             rep.setProtocolClaimMappings(mappings);
         }
         return rep;
@@ -337,13 +337,14 @@ public class ModelToRepresentation {
         return providerRep;
     }
 
-    public static ProtocolClaimMappingRepresentation toRepresentation(ProtocolClaimMappingModel model) {
-        ProtocolClaimMappingRepresentation rep = new ProtocolClaimMappingRepresentation();
+    public static ProtocolMapperRepresentation toRepresentation(ProtocolMapperModel model) {
+        ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
         rep.setId(model.getId());
         rep.setProtocol(model.getProtocol());
         rep.setProtocolClaim(model.getProtocolClaim());
         rep.setSourceAttribute(model.getSourceAttribute());
         rep.setSource(model.getSource().name());
+        rep.setProtocolMapper(model.getProtocolMapper());
         rep.setAppliedByDefault(model.isAppliedByDefault());
         return rep;
     }
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 a4b87ba..6c41613 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
@@ -13,7 +13,7 @@ import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
@@ -27,7 +27,7 @@ import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.FederatedIdentityRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.representations.idm.OAuthClientRepresentation;
-import org.keycloak.representations.idm.ProtocolClaimMappingRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.ScopeMappingRepresentation;
@@ -461,7 +461,7 @@ public class RepresentationToModel {
         }
 
         if (resourceRep.getProtocolClaimMappings() != null) {
-            applicationModel.addProtocolClaimMappings(resourceRep.getProtocolClaimMappings());
+            applicationModel.addProtocolMappers(resourceRep.getProtocolClaimMappings());
         }
 
         return applicationModel;
@@ -638,7 +638,7 @@ public class RepresentationToModel {
         }
 
         if (rep.getProtocolClaimMappings() != null) {
-            model.addProtocolClaimMappings(rep.getProtocolClaimMappings());
+            model.addProtocolMappers(rep.getProtocolClaimMappings());
         }
 
     }
@@ -774,8 +774,8 @@ public class RepresentationToModel {
 
     private static void importProtocolClaimMappings(RealmRepresentation rep, RealmModel newRealm) {
         if (rep.getProtocolClaimMappings() != null) {
-            for (ProtocolClaimMappingRepresentation representation : rep.getProtocolClaimMappings()) {
-                newRealm.addProtocolClaimMapping(toModel(representation));
+            for (ProtocolMapperRepresentation representation : rep.getProtocolClaimMappings()) {
+                newRealm.addProtocolMapper(toModel(representation));
             }
         }
     }
@@ -805,14 +805,15 @@ public class RepresentationToModel {
         return model;
     }
 
-    public static ProtocolClaimMappingModel toModel(ProtocolClaimMappingRepresentation rep) {
-        ProtocolClaimMappingModel model = new ProtocolClaimMappingModel();
+    public static ProtocolMapperModel toModel(ProtocolMapperRepresentation rep) {
+        ProtocolMapperModel model = new ProtocolMapperModel();
         model.setId(rep.getId());
         model.setAppliedByDefault(rep.isAppliedByDefault());
-        model.setSource(ProtocolClaimMappingModel.Source.valueOf(rep.getSource()));
+        model.setSource(ProtocolMapperModel.Source.valueOf(rep.getSource()));
         model.setSourceAttribute(rep.getSourceAttribute());
         model.setProtocol(rep.getProtocol());
         model.setProtocolClaim(rep.getProtocolClaim());
+        model.setProtocolMapper(rep.getProtocolMapper());
         return model;
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
index 9055fa7..83f5490 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/ClientAdapter.java
@@ -1,7 +1,7 @@
 package org.keycloak.models.cache;
 
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
@@ -281,21 +281,21 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        if (updatedClient != null) return updatedClient.getProtocolClaimMappings();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        if (updatedClient != null) return updatedClient.getProtocolMappers();
         return cachedClient.getProtocolClaimMappings();    }
 
     @Override
-    public void addProtocolClaimMappings(Set<String> mappingIds) {
+    public void addProtocolMappers(Set<String> mappingIds) {
         getDelegateForUpdate();
-        updatedClient.addProtocolClaimMappings(mappingIds);
+        updatedClient.addProtocolMappers(mappingIds);
 
     }
 
     @Override
-    public void removeProtocolClaimMappings(Set<String> mappingIds) {
+    public void removeProtocolMappers(Set<String> mappingIds) {
         getDelegateForUpdate();
-        updatedClient.removeProtocolClaimMappings(mappingIds);
+        updatedClient.removeProtocolMappers(mappingIds);
 
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
index f6c7096..08fa1e7 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedClient.java
@@ -1,7 +1,7 @@
 package org.keycloak.models.cache.entities;
 
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
@@ -36,7 +36,7 @@ public class CachedClient {
     protected Set<String> scope = new HashSet<String>();
     protected Set<String> webOrigins = new HashSet<String>();
     private List<String> allowedIdentityProviders = new ArrayList<String>();
-    private Set<ProtocolClaimMappingModel> protocolClaimMappings = new HashSet<ProtocolClaimMappingModel>();
+    private Set<ProtocolMapperModel> protocolClaimMappings = new HashSet<ProtocolMapperModel>();
 
     public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
         id = model.getId();
@@ -58,7 +58,7 @@ public class CachedClient {
             scope.add(role.getId());
         }
         this.allowedIdentityProviders = model.getAllowedIdentityProviders();
-        protocolClaimMappings.addAll(model.getProtocolClaimMappings());
+        protocolClaimMappings.addAll(model.getProtocolMappers());
     }
 
     public String getId() {
@@ -137,7 +137,7 @@ public class CachedClient {
         return this.allowedIdentityProviders.contains(providerId);
     }
 
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
+    public Set<ProtocolMapperModel> getProtocolClaimMappings() {
         return protocolClaimMappings;
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
index c4a7796..81ddc57 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/entities/CachedRealm.java
@@ -6,7 +6,7 @@ import org.keycloak.models.ClaimTypeModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RequiredCredentialModel;
@@ -71,7 +71,7 @@ public class CachedRealm {
     private List<UserFederationProviderModel> userFederationProviders = new ArrayList<UserFederationProviderModel>();
     private List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
     private Set<ClaimTypeModel> claimTypes = new HashSet<ClaimTypeModel>();
-    private Set<ProtocolClaimMappingModel> claimMappings = new HashSet<ProtocolClaimMappingModel>();
+    private Set<ProtocolMapperModel> claimMappings = new HashSet<ProtocolMapperModel>();
 
     private Map<String, String> browserSecurityHeaders = new HashMap<String, String>();
     private Map<String, String> smtpConfig = new HashMap<String, String>();
@@ -353,7 +353,7 @@ public class CachedRealm {
         return claimTypes;
     }
 
-    public Set<ProtocolClaimMappingModel> getClaimMappings() {
+    public Set<ProtocolMapperModel> getClaimMappings() {
         return claimMappings;
     }
 }
diff --git a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
index 8c83451..21d32cc 100755
--- a/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
+++ b/model/invalidation-cache/model-adapters/src/main/java/org/keycloak/models/cache/RealmAdapter.java
@@ -8,7 +8,7 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
@@ -886,34 +886,34 @@ public class RealmAdapter implements RealmModel {
 
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        if (updated != null) return updated.getProtocolClaimMappings();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        if (updated != null) return updated.getProtocolMappers();
         return cached.getClaimMappings();
      }
 
     @Override
-    public ProtocolClaimMappingModel addProtocolClaimMapping(ProtocolClaimMappingModel model) {
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
         getDelegateForUpdate();
-        return updated.addProtocolClaimMapping(model);
+        return updated.addProtocolMapper(model);
     }
 
     @Override
-    public void removeProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
         getDelegateForUpdate();
-        updated.removeProtocolClaimMapping(mapping);
+        updated.removeProtocolMapper(mapping);
 
     }
 
     @Override
-    public void updateProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
         getDelegateForUpdate();
-        updated.updateProtocolClaimMapping(mapping);
+        updated.updateProtocolMapper(mapping);
 
     }
 
     @Override
-    public ProtocolClaimMappingModel getProtocolClaimMappingById(String id) {
-        for (ProtocolClaimMappingModel mapping : cached.getClaimMappings()) {
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        for (ProtocolMapperModel mapping : cached.getClaimMappings()) {
             if (mapping.getId().equals(id)) return mapping;
         }
         return null;
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index 8410cfc..9faace4 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -1,13 +1,13 @@
 package org.keycloak.models.jpa;
 
 import org.keycloak.models.ClientModel;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleContainerModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.jpa.entities.ClientEntity;
 import org.keycloak.models.jpa.entities.IdentityProviderEntity;
-import org.keycloak.models.jpa.entities.ProtocolClaimMappingEntity;
+import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
 import org.keycloak.models.jpa.entities.RoleEntity;
 import org.keycloak.models.jpa.entities.ScopeMappingEntity;
 
@@ -357,15 +357,15 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        Set<ProtocolClaimMappingModel> mappings = new HashSet<ProtocolClaimMappingModel>();
-        for (ProtocolClaimMappingEntity entity : this.entity.getProtocolClaimMappings()) {
-            ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> mappings = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : this.entity.getProtocolMappers()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
             mapping.setId(entity.getId());
             mapping.setProtocol(entity.getProtocol());
             mapping.setProtocolClaim(entity.getProtocolClaim());
             mapping.setAppliedByDefault(entity.isAppliedByDefault());
-            mapping.setSource(ProtocolClaimMappingModel.Source.valueOf(entity.getSource()));
+            mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
             mapping.setSourceAttribute(entity.getSourceAttribute());
             mappings.add(mapping);
         }
@@ -373,15 +373,15 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public void addProtocolClaimMappings(Set<String> mappings) {
-        Collection<ProtocolClaimMappingEntity> entities = entity.getProtocolClaimMappings();
+    public void addProtocolMappers(Set<String> mappings) {
+        Collection<ProtocolMapperEntity> entities = entity.getProtocolMappers();
         Set<String> already = new HashSet<String>();
-        for (ProtocolClaimMappingEntity rel : entities) {
+        for (ProtocolMapperEntity rel : entities) {
             already.add(rel.getId());
         }
         for (String providerId : mappings) {
             if (!already.contains(providerId)) {
-                ProtocolClaimMappingEntity mapping = em.find(ProtocolClaimMappingEntity.class, providerId);
+                ProtocolMapperEntity mapping = em.find(ProtocolMapperEntity.class, providerId);
                 if (mapping != null) {
                     entities.add(mapping);
                 }
@@ -391,13 +391,13 @@ public abstract class ClientAdapter implements ClientModel {
     }
 
     @Override
-    public void removeProtocolClaimMappings(Set<String> mappings) {
-        Collection<ProtocolClaimMappingEntity> entities = entity.getProtocolClaimMappings();
-        List<ProtocolClaimMappingEntity> remove = new LinkedList<ProtocolClaimMappingEntity>();
-        for (ProtocolClaimMappingEntity rel : entities) {
+    public void removeProtocolMappers(Set<String> mappings) {
+        Collection<ProtocolMapperEntity> entities = entity.getProtocolMappers();
+        List<ProtocolMapperEntity> remove = new LinkedList<ProtocolMapperEntity>();
+        for (ProtocolMapperEntity rel : entities) {
             if (mappings.contains(rel.getId())) remove.add(rel);
         }
-        for (ProtocolClaimMappingEntity entity : remove) {
+        for (ProtocolMapperEntity entity : remove) {
             entities.remove(entity);
         }
         em.flush();
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
index 36e5888..ec8929e 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ClientEntity.java
@@ -78,8 +78,8 @@ public abstract class ClientEntity {
     Collection<IdentityProviderEntity> allowedIdentityProviders = new ArrayList<IdentityProviderEntity>();
 
     @OneToMany(cascade ={CascadeType.REMOVE})
-    @JoinTable(name="CLIENT_PROTOCOL_CLAIM_MAPPING", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="MAPPING_ID")})
-    Collection<ProtocolClaimMappingEntity> protocolClaimMappings = new ArrayList<ProtocolClaimMappingEntity>();
+    @JoinTable(name="CLIENT_PROTOCOL_MAPPER", joinColumns = { @JoinColumn(name="CLIENT_ID")}, inverseJoinColumns = { @JoinColumn(name="MAPPING_ID")})
+    Collection<ProtocolMapperEntity> protocolMappers = new ArrayList<ProtocolMapperEntity>();
 
     public RealmEntity getRealm() {
         return realm;
@@ -201,11 +201,11 @@ public abstract class ClientEntity {
         this.allowedIdentityProviders = allowedIdentityProviders;
     }
 
-    public Collection<ProtocolClaimMappingEntity> getProtocolClaimMappings() {
-        return protocolClaimMappings;
+    public Collection<ProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
     }
 
-    public void setProtocolClaimMappings(Collection<ProtocolClaimMappingEntity> protocolClaimMappings) {
-        this.protocolClaimMappings = protocolClaimMappings;
+    public void setProtocolMappers(Collection<ProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
     }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 5590e7f..e9cdda1 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -96,7 +96,7 @@ public class RealmEntity {
     Collection<ClaimTypeEntity> claimTypes = new ArrayList<ClaimTypeEntity>();
 
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
-    Collection<ProtocolClaimMappingEntity> protocolClaimMappings = new ArrayList<ProtocolClaimMappingEntity>();
+    Collection<ProtocolMapperEntity> protocolClaimMappings = new ArrayList<ProtocolMapperEntity>();
 
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
     Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
@@ -447,11 +447,11 @@ public class RealmEntity {
         this.claimTypes = claimTypes;
     }
 
-    public Collection<ProtocolClaimMappingEntity> getProtocolClaimMappings() {
+    public Collection<ProtocolMapperEntity> getProtocolClaimMappings() {
         return protocolClaimMappings;
     }
 
-    public void setProtocolClaimMappings(Collection<ProtocolClaimMappingEntity> protocolClaimMappings) {
+    public void setProtocolClaimMappings(Collection<ProtocolMapperEntity> protocolClaimMappings) {
         this.protocolClaimMappings = protocolClaimMappings;
     }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index af9d916..f294bbd 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -8,7 +8,7 @@ import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RequiredCredentialModel;
 import org.keycloak.models.RoleModel;
@@ -17,7 +17,7 @@ import org.keycloak.models.jpa.entities.ApplicationEntity;
 import org.keycloak.models.jpa.entities.ClaimTypeEntity;
 import org.keycloak.models.jpa.entities.IdentityProviderEntity;
 import org.keycloak.models.jpa.entities.OAuthClientEntity;
-import org.keycloak.models.jpa.entities.ProtocolClaimMappingEntity;
+import org.keycloak.models.jpa.entities.ProtocolMapperEntity;
 import org.keycloak.models.jpa.entities.RealmAttributeEntity;
 import org.keycloak.models.jpa.entities.RealmEntity;
 import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
@@ -1257,45 +1257,48 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        Set<ProtocolClaimMappingModel> mappings = new HashSet<ProtocolClaimMappingModel>();
-        for (ProtocolClaimMappingEntity entity : realm.getProtocolClaimMappings()) {
-            ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> mappings = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : realm.getProtocolClaimMappings()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
             mapping.setId(entity.getId());
             mapping.setProtocol(entity.getProtocol());
             mapping.setProtocolClaim(entity.getProtocolClaim());
             mapping.setAppliedByDefault(entity.isAppliedByDefault());
-            mapping.setSource(ProtocolClaimMappingModel.Source.valueOf(entity.getSource()));
+            mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
             mapping.setSourceAttribute(entity.getSourceAttribute());
+            mapping.setProtocolMapper(entity.getProtocolMapper());
             mappings.add(mapping);
         }
         return mappings;
     }
 
     @Override
-    public ProtocolClaimMappingModel addProtocolClaimMapping(ProtocolClaimMappingModel model) {
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
         String id = model.getId() == null ? KeycloakModelUtils.generateId() : model.getId();
-        ProtocolClaimMappingEntity entity = new ProtocolClaimMappingEntity();
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
         entity.setId(id);
         entity.setSourceAttribute(model.getSourceAttribute());
         entity.setProtocol(model.getProtocol());
         entity.setProtocolClaim(model.getProtocolClaim());
         entity.setSource(model.getSource().name());
+        entity.setProtocolMapper(model.getProtocolMapper());
         entity.setAppliedByDefault(model.isAppliedByDefault());
         entity.setRealm(realm);
         em.persist(entity);
-        ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
         mapping.setId(entity.getId());
         mapping.setProtocol(entity.getProtocol());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
         mapping.setProtocolClaim(entity.getProtocolClaim());
         mapping.setAppliedByDefault(entity.isAppliedByDefault());
-        mapping.setSource(ProtocolClaimMappingModel.Source.valueOf(entity.getSource()));
+        mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
         mapping.setSourceAttribute(entity.getSourceAttribute());
         return mapping;
     }
 
-    protected ProtocolClaimMappingEntity getProtocolClaimMapping(String id) {
-        for (ProtocolClaimMappingEntity entity : realm.getProtocolClaimMappings()) {
+    protected ProtocolMapperEntity getProtocolClaimMapping(String id) {
+        for (ProtocolMapperEntity entity : realm.getProtocolClaimMappings()) {
             if (entity.getId().equals(id)) {
                 return entity;
             }
@@ -1305,8 +1308,8 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public void removeProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
-        ProtocolClaimMappingEntity toDelete = getProtocolClaimMapping(mapping.getId());
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity toDelete = getProtocolClaimMapping(mapping.getId());
         if (toDelete != null) {
             realm.getProtocolClaimMappings().remove(toDelete);
             em.remove(toDelete);
@@ -1315,8 +1318,8 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public void updateProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
-        ProtocolClaimMappingEntity entity = getProtocolClaimMapping(mapping.getId());
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolClaimMapping(mapping.getId());
         entity.setProtocol(mapping.getProtocol());
         entity.setProtocolClaim(mapping.getProtocolClaim());
         entity.setAppliedByDefault(mapping.isAppliedByDefault());
@@ -1327,15 +1330,15 @@ public class RealmAdapter implements RealmModel {
     }
 
     @Override
-    public ProtocolClaimMappingModel getProtocolClaimMappingById(String id) {
-        ProtocolClaimMappingEntity entity = getProtocolClaimMapping(id);
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolClaimMapping(id);
         if (entity == null) return null;
-        ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
         mapping.setId(entity.getId());
         mapping.setProtocol(entity.getProtocol());
         mapping.setProtocolClaim(entity.getProtocolClaim());
         mapping.setAppliedByDefault(entity.isAppliedByDefault());
-        mapping.setSource(ProtocolClaimMappingModel.Source.valueOf(entity.getSource()));
+        mapping.setSource(ProtocolMapperModel.Source.valueOf(entity.getSource()));
         mapping.setSourceAttribute(entity.getSourceAttribute());
         return mapping;
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index 11ecd61..1a6990d 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -4,7 +4,7 @@ import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RoleModel;
@@ -293,24 +293,24 @@ public abstract class ClientAdapter<T extends MongoIdentifiableEntity> extends A
     }
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        Set<ProtocolClaimMappingModel> result = new HashSet<ProtocolClaimMappingModel>();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
         for (String id : getMongoEntityAsClient().getProtocolClaimMappings()) {
-            ProtocolClaimMappingModel model = getRealm().getProtocolClaimMappingById(id);
+            ProtocolMapperModel model = getRealm().getProtocolMapperById(id);
             if (model != null) result.add(model);
         }
         return result;
     }
 
     @Override
-    public void addProtocolClaimMappings(Set<String> mappingIds) {
+    public void addProtocolMappers(Set<String> mappingIds) {
         getMongoEntityAsClient().getProtocolClaimMappings().addAll(mappingIds);
         updateMongoEntity();
 
     }
 
     @Override
-    public void removeProtocolClaimMappings(Set<String> mappingIds) {
+    public void removeProtocolMappers(Set<String> mappingIds) {
         getMongoEntityAsClient().getProtocolClaimMappings().removeAll(mappingIds);
         updateMongoEntity();
     }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index da4766c..0dfac8b 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -11,7 +11,7 @@ import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.OAuthClientModel;
 import org.keycloak.models.PasswordPolicy;
-import org.keycloak.models.ProtocolClaimMappingModel;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RealmProvider;
 import org.keycloak.models.RequiredCredentialModel;
@@ -19,7 +19,7 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserFederationProviderModel;
 import org.keycloak.models.entities.ClaimTypeEntity;
 import org.keycloak.models.entities.IdentityProviderEntity;
-import org.keycloak.models.entities.ProtocolClaimMappingEntity;
+import org.keycloak.models.entities.ProtocolMapperEntity;
 import org.keycloak.models.entities.RequiredCredentialEntity;
 import org.keycloak.models.entities.UserFederationProviderEntity;
 import org.keycloak.models.mongo.keycloak.entities.MongoApplicationEntity;
@@ -787,10 +787,10 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
-    public Set<ProtocolClaimMappingModel> getProtocolClaimMappings() {
-        Set<ProtocolClaimMappingModel> result = new HashSet<ProtocolClaimMappingModel>();
-        for (ProtocolClaimMappingEntity entity : realm.getClaimMappings()) {
-            ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+    public Set<ProtocolMapperModel> getProtocolMappers() {
+        Set<ProtocolMapperModel> result = new HashSet<ProtocolMapperModel>();
+        for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
+            ProtocolMapperModel mapping = new ProtocolMapperModel();
             mapping.setId(entity.getId());
             mapping.setProtocolClaim(entity.getProtocolClaim());
             mapping.setProtocol(entity.getProtocol());
@@ -802,8 +802,8 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
     }
 
     @Override
-    public ProtocolClaimMappingModel addProtocolClaimMapping(ProtocolClaimMappingModel model) {
-        ProtocolClaimMappingEntity entity = new ProtocolClaimMappingEntity();
+    public ProtocolMapperModel addProtocolMapper(ProtocolMapperModel model) {
+        ProtocolMapperEntity entity = new ProtocolMapperEntity();
         if (model.getId() != null) entity.setId(model.getId());
         else entity.setId(KeycloakModelUtils.generateId());
         entity.setSourceAttribute(model.getSourceAttribute());
@@ -811,21 +811,23 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
         entity.setProtocolClaim(model.getProtocolClaim());
         entity.setSource(model.getSource());
         entity.setAppliedByDefault(model.isAppliedByDefault());
+        entity.setProtocolMapper(model.getProtocolMapper());
         realm.getClaimMappings().add(entity);
         updateRealm();
-        ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
         mapping.setId(entity.getId());
         mapping.setProtocol(entity.getProtocol());
         mapping.setProtocolClaim(entity.getProtocolClaim());
         mapping.setAppliedByDefault(entity.isAppliedByDefault());
         mapping.setSource(entity.getSource());
         mapping.setSourceAttribute(entity.getSourceAttribute());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
         return mapping;
     }
 
     @Override
-    public void removeProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
-        for (ProtocolClaimMappingEntity entity : realm.getClaimMappings()) {
+    public void removeProtocolMapper(ProtocolMapperModel mapping) {
+        for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
             if (entity.getId().equals(mapping.getId())) {
                 realm.getClaimMappings().remove(entity);
                 updateRealm();
@@ -835,8 +837,8 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
 
     }
 
-    protected ProtocolClaimMappingEntity getProtocolClaimMapping(String id) {
-        for (ProtocolClaimMappingEntity entity : realm.getClaimMappings()) {
+    protected ProtocolMapperEntity getProtocolClaimMapping(String id) {
+        for (ProtocolMapperEntity entity : realm.getClaimMappings()) {
             if (entity.getId().equals(id)) {
                 return entity;
             }
@@ -847,28 +849,30 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
 
 
     @Override
-    public void updateProtocolClaimMapping(ProtocolClaimMappingModel mapping) {
-        ProtocolClaimMappingEntity entity = getProtocolClaimMapping(mapping.getId());
+    public void updateProtocolMapper(ProtocolMapperModel mapping) {
+        ProtocolMapperEntity entity = getProtocolClaimMapping(mapping.getId());
         entity.setProtocol(mapping.getProtocol());
         entity.setProtocolClaim(mapping.getProtocolClaim());
         entity.setAppliedByDefault(mapping.isAppliedByDefault());
         entity.setSource(mapping.getSource());
         entity.setSourceAttribute(mapping.getSourceAttribute());
+        entity.setProtocolMapper(mapping.getProtocolMapper());
         updateRealm();
 
     }
 
     @Override
-    public ProtocolClaimMappingModel getProtocolClaimMappingById(String id) {
-        ProtocolClaimMappingEntity entity = getProtocolClaimMapping(id);
+    public ProtocolMapperModel getProtocolMapperById(String id) {
+        ProtocolMapperEntity entity = getProtocolClaimMapping(id);
         if (entity == null) return null;
-        ProtocolClaimMappingModel mapping = new ProtocolClaimMappingModel();
+        ProtocolMapperModel mapping = new ProtocolMapperModel();
         mapping.setId(entity.getId());
         mapping.setProtocol(entity.getProtocol());
         mapping.setProtocolClaim(entity.getProtocolClaim());
         mapping.setAppliedByDefault(entity.isAppliedByDefault());
         mapping.setSource(entity.getSource());
         mapping.setSourceAttribute(entity.getSourceAttribute());
+        mapping.setProtocolMapper(entity.getProtocolMapper());
         return mapping;
     }
 
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
index b21af78..d8fd673 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java
@@ -17,10 +17,9 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.ClientSessionCode;
-import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.resources.flows.Flows;
 import org.keycloak.util.StreamUtil;
@@ -215,7 +214,7 @@ public class SamlService {
             String redirect = null;
             URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL();
             if (redirectUri != null && !"null".equals(redirectUri)) {  // "null" is for testing purposes
-                redirect = OpenIDConnectService.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client);
+                redirect = OIDCLoginProtocolService.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client);
             } else {
                 if (bindingType.equals(SamlProtocol.SAML_POST_BINDING)) {
                     redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE);
@@ -339,7 +338,7 @@ public class SamlService {
             }
 
             if (redirectUri != null) {
-                redirectUri = OpenIDConnectService.verifyRedirectUri(uriInfo, redirectUri, realm, client);
+                redirectUri = OIDCLoginProtocolService.verifyRedirectUri(uriInfo, redirectUri, realm, client);
                 if (redirectUri == null) {
                     return Flows.forwardToSecurityFailurePage(session, realm, uriInfo, "Invalid redirect uri.");
                 }
diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocol.java b/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
index 1d6a2fa..7bd4d03 100755
--- a/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/LoginProtocol.java
@@ -1,12 +1,9 @@
 package org.keycloak.protocol;
 
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OpenIDConnect;
 import org.keycloak.provider.Provider;
 import org.keycloak.services.managers.ClientSessionCode;
 
diff --git a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
index 4bd4bea..0de9bf8 100755
--- a/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/LoginProtocolFactory.java
@@ -1,14 +1,18 @@
 package org.keycloak.protocol;
 
 import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.provider.ProviderFactory;
 import org.keycloak.services.managers.AuthenticationManager;
 
+import java.util.List;
+
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public interface LoginProtocolFactory extends ProviderFactory<LoginProtocol> {
+    //List<ProtocolMapperModel> getDefaultProtocolMappers();
     Object createProtocolEndpoint(RealmModel realm, EventBuilder event, AuthenticationManager authManager);
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/AbstractOIDCProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/AbstractOIDCProtocolMapper.java
new file mode 100755
index 0000000..9b3fb60
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/AbstractOIDCProtocolMapper.java
@@ -0,0 +1,33 @@
+package org.keycloak.protocol.oidc;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.protocol.ProtocolMapper;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
+
+    @Override
+    public String getProtocol() {
+        return OIDCLoginProtocol.LOGIN_PROTOCOL;
+    }
+
+    @Override
+    public void close() {
+
+    }
+
+    @Override
+    public final ProtocolMapper create(KeycloakSession session) {
+        throw new RuntimeException("UNSUPPORTED METHOD");
+    }
+
+    @Override
+    public void init(Config.Scope config) {
+
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCAccessTokenTransformer.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAccessTokenTransformer.java
new file mode 100755
index 0000000..c63385f
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAccessTokenTransformer.java
@@ -0,0 +1,17 @@
+package org.keycloak.protocol.oidc;
+
+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;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface OIDCAccessTokenTransformer {
+
+    AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                               UserSessionModel userSession, ClientSessionModel clientSession);
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCAttributeToTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAttributeToTokenMapper.java
new file mode 100755
index 0000000..9ff207f
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAttributeToTokenMapper.java
@@ -0,0 +1,84 @@
+package org.keycloak.protocol.oidc;
+
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.AccessToken;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Mappings user data to an ID Token claim.  Source can be from UserModel.getAttributes(), a get method on UserModel, UserSession.getNote
+ * or ClientSession.getNote.  Claim can be a full qualified nested object name, i.e. "address.country".  This will create a nested
+ * json object within the toke claim.
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class OIDCAttributeToTokenMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenTransformer {
+    @Override
+    public String getId() {
+        return "oidc-attribute-claim-mapper";
+    }
+
+    @Override
+    public String getDisplayType() {
+        return "Attribute Claim Mapper";
+    }
+
+    @Override
+    public AccessToken transformToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                      UserSessionModel userSession, ClientSessionModel clientSession) {
+        String attributeValue = null;
+        UserModel user = userSession.getUser();
+        switch (mappingModel.getSource()) {
+            case USER_ATTRIBUTE:
+                attributeValue = user.getAttribute(mappingModel.getSourceAttribute());
+                break;
+            case USER_SESSION_NOTE:
+                attributeValue = userSession.getNote(mappingModel.getSourceAttribute());
+                break;
+            case CLIENT_SESSION_NOTE:
+                attributeValue = clientSession.getNote(mappingModel.getSourceAttribute());
+                break;
+            case USER_MODEL:
+                attributeValue = getUserModelValue(user, mappingModel);
+                break;
+        }
+        if (attributeValue == null) return token;
+        String[] split = mappingModel.getProtocolClaim().split(".");
+        Map<String, Object> jsonObject = token.getOtherClaims();
+        for (int i = 0; i < split.length; i++) {
+            if (i == split.length - 1) {
+                jsonObject.put(split[i], attributeValue);
+            } else {
+                Map<String, Object> nested = (Map<String, Object>)jsonObject.get(split[i]);
+                if (nested == null) {
+                    nested = new HashMap<String, Object>();
+                    jsonObject.put(split[i], nested);
+                    jsonObject = nested;
+                }
+            }
+        }
+        return token;
+    }
+
+    protected String getUserModelValue(UserModel user, ProtocolMapperModel model) {
+        String sourceAttribute = model.getSourceAttribute();
+        if (sourceAttribute == null) return null;
+
+        String methodName = "get" + Character.toUpperCase(sourceAttribute.charAt(0)) + sourceAttribute.substring(1);
+        try {
+            Method method = UserModel.class.getMethod(methodName);
+            Object val = method.invoke(user);
+            if (val != null) return val.toString();
+        } catch (Exception ignore) {
+
+        }
+        return 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 2204103..4c56df7 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -13,6 +13,7 @@ import org.keycloak.models.ClaimMask;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 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;
@@ -85,11 +86,25 @@ public class TokenManager {
             throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
         }
 
+        ClientSessionModel clientSession = null;
+        for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) {
+            if (clientSessionModel.getId().equals(refreshToken.getClientSession())) {
+                clientSession = clientSessionModel;
+                break;
+            }
+        }
+
+        if (clientSession == null) {
+            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Client session not active", "Client session not active");
+
+        }
+
         verifyAccess(refreshToken, realm, client, user);
 
-        AccessToken accessToken = initToken(realm, client, user, userSession);
+        AccessToken accessToken = initToken(realm, client, user, userSession, clientSession);
         accessToken.setRealmAccess(refreshToken.getRealmAccess());
         accessToken.setResourceAccess(refreshToken.getResourceAccess());
+        accessToken = transformToken(accessToken, realm, client, user, userSession, clientSession);
 
         userSession.setLastSessionRefresh(currentTime);
 
@@ -117,11 +132,12 @@ public class TokenManager {
         return refreshToken;
     }
 
-    public AccessToken createClientAccessToken(Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
-        AccessToken token = initToken(realm, client, user, session);
+    public AccessToken createClientAccessToken(Set<RoleModel> requestedRoles, RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
+        AccessToken token = initToken(realm, client, user, session, clientSession);
         for (RoleModel role : requestedRoles) {
             addComposites(token, role);
         }
+        token = transformToken(token, realm, client, user, session, clientSession);
         return token;
     }
 
@@ -234,28 +250,25 @@ public class TokenManager {
             if (user.getLastName() != null) fullName.append(user.getLastName());
             claimSet.setName(fullName.toString());
         }
-    }
 
-    protected IDToken initIDToken(RealmModel realm, ClientModel claimer, UserModel client, UserModel user) {
-        IDToken token = new IDToken();
-        token.id(KeycloakModelUtils.generateId());
-        token.subject(user.getId());
-        token.audience(claimer.getClientId());
-        token.issuedNow();
-        token.issuedFor(client.getUsername());
-        token.issuer(realm.getName());
-        if (realm.getAccessTokenLifespan() > 0) {
-            token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
+        Set<ProtocolMapperModel> mappings = model.getProtocolMappers();
+        for (ProtocolMapperModel mapping : mappings) {
+            if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue;
+
         }
+    }
+
+    protected AccessToken transformToken(AccessToken token, RealmModel realm, ClientModel client, UserModel user,
+                                         UserSessionModel session, ClientSessionModel clientSession) {
         UserClaimSet claimSet = token.getUserClaimSet();
-        initClaims(claimSet, claimer, user);
+        initClaims(claimSet, client, user);
         return token;
     }
 
 
-
-    protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session) {
+    protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
         AccessToken token = new AccessToken();
+        if (clientSession != null) token.clientSession(clientSession.getId());
         token.id(KeycloakModelUtils.generateId());
         token.subject(user.getId());
         token.audience(client.getClientId());
@@ -272,8 +285,6 @@ public class TokenManager {
         if (allowedOrigins != null) {
             token.setAllowedOrigins(allowedOrigins);
         }
-        UserClaimSet claimSet = token.getUserClaimSet();
-        initClaims(claimSet, client, user);
         return token;
     }
 
@@ -339,9 +350,9 @@ public class TokenManager {
             return this;
         }
 
-        public AccessTokenResponseBuilder generateAccessToken(String scopeParam, ClientModel client, UserModel user, UserSessionModel session) {
+        public AccessTokenResponseBuilder generateAccessToken(String scopeParam, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession) {
             Set<RoleModel> requestedRoles = getAccess(scopeParam, client, user);
-            accessToken = createClientAccessToken(requestedRoles, realm, client, user, session);
+            accessToken = createClientAccessToken(requestedRoles, realm, client, user, session, clientSession);
             return this;
         }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
old mode 100644
new mode 100755
index 5e69d05..7a0e8a8
--- a/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/UserInfoService.java
@@ -68,10 +68,10 @@ public class UserInfoService {
 
     private final TokenManager tokenManager;
     private final AppAuthManager appAuthManager;
-    private final OpenIDConnectService openIdConnectService;
+    private final OIDCLoginProtocolService openIdConnectService;
     private final RealmModel realmModel;
 
-    public UserInfoService(OpenIDConnectService openIDConnectService) {
+    public UserInfoService(OIDCLoginProtocolService openIDConnectService) {
         this.realmModel = openIDConnectService.getRealm();
 
         if (this.realmModel == null) {
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
new file mode 100755
index 0000000..8697d72
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapper.java
@@ -0,0 +1,13 @@
+package org.keycloak.protocol;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper> {
+    String getProtocol();
+    String getDisplayType();
+}
diff --git a/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java b/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java
new file mode 100755
index 0000000..421319e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/ProtocolMapperSpi.java
@@ -0,0 +1,27 @@
+package org.keycloak.protocol;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ProtocolMapperSpi implements Spi {
+
+    @Override
+    public String getName() {
+        return "protocol-mapper";
+    }
+
+    @Override
+    public Class<? extends Provider> getProviderClass() {
+        return ProtocolMapper.class;
+    }
+
+    @Override
+    public Class<? extends ProviderFactory> getProviderFactoryClass() {
+        return ProtocolMapper.class;
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index e1402c9..240d5cb 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -18,7 +18,6 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionProvider;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.protocol.oidc.OpenIDConnect;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index 241b37a..337f01d 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -48,8 +48,8 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.TimeBasedOTP;
-import org.keycloak.protocol.oidc.OpenIDConnect;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.services.ForbiddenException;
@@ -681,7 +681,7 @@ public class AccountService {
                     ClientSessionCode clientSessionCode = new ClientSessionCode(realm, clientSession);
                     clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE);
                     clientSession.setRedirectUri(redirectUri);
-                    clientSession.setNote(OpenIDConnect.STATE_PARAM, UUID.randomUUID().toString());
+                    clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
 
                     return Response.temporaryRedirect(
                             Urls.identityProviderAuthnRequest(this.uriInfo.getBaseUri(), providerId, realm.getName(), clientSessionCode.getCode()))
@@ -769,7 +769,7 @@ public class AccountService {
 
     private Response login(String path) {
         OAuthRedirect oauth = new OAuthRedirect();
-        String authUrl = OpenIDConnectService.loginPageUrl(uriInfo).build(realm.getName()).toString();
+        String authUrl = OIDCLoginProtocolService.loginPageUrl(uriInfo).build(realm.getName()).toString();
         oauth.setAuthUrl(authUrl);
 
         oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_APP);
@@ -822,7 +822,7 @@ public class AccountService {
         ApplicationModel application = realm.getApplicationByName(referrer);
         if (application != null) {
             if (referrerUri != null) {
-                referrerUri = OpenIDConnectService.verifyRedirectUri(uriInfo, referrerUri, realm, application);
+                referrerUri = OIDCLoginProtocolService.verifyRedirectUri(uriInfo, referrerUri, realm, application);
             } else {
                 referrerUri = ResolveRelative.resolveRelativeUri(uriInfo.getRequestUri(), application.getBaseUrl());
             }
@@ -833,7 +833,7 @@ public class AccountService {
         } else if (referrerUri != null) {
             ClientModel client = realm.getOAuthClient(referrer);
             if (client != null) {
-                referrerUri = OpenIDConnectService.verifyRedirectUri(uriInfo, referrerUri, realm, application);
+                referrerUri = OIDCLoginProtocolService.verifyRedirectUri(uriInfo, referrerUri, realm, application);
 
                 if (referrerUri != null) {
                     return new String[]{referrer, referrerUri};
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index 0f8df52..13dbe25 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -18,7 +18,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.ApplicationManager;
 import org.keycloak.services.managers.AuthenticationManager;
@@ -252,7 +252,7 @@ public class AdminConsole {
         URI redirect = AdminRoot.adminConsoleUrl(uriInfo).path("index.html").build(realm.getName());
 
         return Response.status(302).location(
-                OpenIDConnectService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
+                OIDCLoginProtocolService.logoutUrl(uriInfo).queryParam("redirect_uri", redirect.toString()).build(realm.getName())
         ).build();
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index fd353c8..e508a70 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -23,8 +23,8 @@ import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
-import org.keycloak.protocol.oidc.OpenIDConnect;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.idm.ApplicationMappingsRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
@@ -690,7 +690,7 @@ public class UsersResource {
     @Path("{username}/reset-password-email")
     @PUT
     @Consumes("application/json")
-    public Response resetPasswordEmail(@PathParam("username") String username, @QueryParam(OpenIDConnect.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OpenIDConnect.CLIENT_ID_PARAM) String clientId) {
+    public Response resetPasswordEmail(@PathParam("username") String username, @QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam(OIDCLoginProtocol.CLIENT_ID_PARAM) String clientId) {
         auth.requireManage();
 
         UserModel user = session.users().getUserByUsername(username, realm);
@@ -721,7 +721,7 @@ public class UsersResource {
 
         String redirect;
         if(redirectUri != null){
-            redirect = OpenIDConnectService.verifyRedirectUri(uriInfo,redirectUri,realm,client);
+            redirect = OIDCLoginProtocolService.verifyRedirectUri(uriInfo, redirectUri, realm, client);
             if(redirect == null){
                 return Flows.errors().error("Invalid redirect uri.", Response.Status.BAD_REQUEST);
             }
@@ -733,7 +733,7 @@ public class UsersResource {
         UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false);
         //audit.session(userSession);
         ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
-        clientSession.setAuthMethod(OpenIDConnect.LOGIN_PROTOCOL);
+        clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
         clientSession.setRedirectUri(redirect);
         clientSession.setUserSession(userSession);
         ClientSessionCode accessCode = new ClientSessionCode(realm, clientSession);
diff --git a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
index 0fdbc81..b49058f 100755
--- a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
+++ b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
@@ -30,7 +30,7 @@ import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.ForbiddenException;
 import org.keycloak.util.Time;
 
@@ -154,7 +154,7 @@ public class ClientsManagementService {
     }
 
     protected ApplicationModel authorizeApplication(String authorizationHeader, MultivaluedMap<String, String> formData) {
-        ClientModel client = OpenIDConnectService.authorizeClientBase(authorizationHeader, formData, event, realm);
+        ClientModel client = OIDCLoginProtocolService.authorizeClientBase(authorizationHeader, formData, event, realm);
 
         if (client.isPublicClient()) {
             Map<String, String> error = new HashMap<String, String>();
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
index 3d7b19c..2eb1ed4 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
@@ -22,8 +22,8 @@
 package org.keycloak.services.resources.flows;
 
 import org.keycloak.OAuth2Constants;
-import org.keycloak.protocol.oidc.OpenIDConnect;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.resources.AccountService;
 import org.keycloak.services.resources.IdentityBrokerService;
 import org.keycloak.services.resources.LoginActionsService;
@@ -170,7 +170,7 @@ public class Urls {
     }
 
     private static UriBuilder realmLogout(URI baseUri) {
-        return tokenBase(baseUri).path(OpenIDConnectService.class, "logout");
+        return tokenBase(baseUri).path(OIDCLoginProtocolService.class, "logout");
     }
 
     public static URI realmRegisterAction(URI baseUri, String realmId) {
@@ -182,7 +182,7 @@ public class Urls {
     }
 
     public static URI realmInstalledAppUrnCallback(URI baseUri, String realmId) {
-        return tokenBase(baseUri).path(OpenIDConnectService.class, "installedAppUrnCallback").build(realmId);
+        return tokenBase(baseUri).path(OIDCLoginProtocolService.class, "installedAppUrnCallback").build(realmId);
     }
 
     public static URI realmOauthAction(URI baseUri, String realmId) {
@@ -198,7 +198,7 @@ public class Urls {
     }
 
     private static UriBuilder tokenBase(URI baseUri) {
-        return realmBase(baseUri).path("{realm}/protocol/" + OpenIDConnect.LOGIN_PROTOCOL);
+        return realmBase(baseUri).path("{realm}/protocol/" + OIDCLoginProtocol.LOGIN_PROTOCOL);
     }
 
     private static UriBuilder themeBase(URI baseUri) {
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index 0ed09d0..d5d4867 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -44,7 +44,7 @@ import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.models.utils.TimeBasedOTP;
 import org.keycloak.protocol.LoginProtocol;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.PasswordToken;
 import org.keycloak.representations.idm.CredentialRepresentation;
@@ -119,7 +119,7 @@ public class LoginActionsService {
 
     public static UriBuilder processLoginUrl(UriBuilder baseUriBuilder) {
         UriBuilder uriBuilder = loginActionsBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OpenIDConnectService.class, "processLogin");
+        return uriBuilder.path(OIDCLoginProtocolService.class, "processLogin");
     }
 
     public static UriBuilder processOAuthUrl(UriInfo uriInfo) {
@@ -129,7 +129,7 @@ public class LoginActionsService {
 
     public static UriBuilder processOAuthUrl(UriBuilder baseUriBuilder) {
         UriBuilder uriBuilder = loginActionsBaseUrl(baseUriBuilder);
-        return uriBuilder.path(OpenIDConnectService.class, "processOAuth");
+        return uriBuilder.path(OIDCLoginProtocolService.class, "processOAuth");
     }
 
     public LoginActionsService(RealmModel realm, AuthenticationManager authManager, EventBuilder event) {
diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
index ee11c1e..b4c3284 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -5,7 +5,7 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.PublishedRealmRepresentation;
 import org.keycloak.services.resources.admin.AdminRoot;
 
@@ -68,7 +68,7 @@ public class PublicRealmResource {
     public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
         PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
         rep.setRealm(realm.getName());
-        rep.setTokenServiceUrl(OpenIDConnectService.tokenServiceBaseUrl(uriInfo).build(realm.getName()).toString());
+        rep.setTokenServiceUrl(OIDCLoginProtocolService.tokenServiceBaseUrl(uriInfo).build(realm.getName()).toString());
         rep.setAccountServiceUrl(AccountService.accountServiceBaseUrl(uriInfo).build(realm.getName()).toString());
         rep.setAdminApiUrl(uriInfo.getBaseUriBuilder().path(AdminRoot.class).build().toString());
         rep.setPublicKeyPem(realm.getPublicKeyPem());
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index de6620c..8a50c69 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -11,8 +11,8 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.LoginProtocol;
 import org.keycloak.protocol.LoginProtocolFactory;
-import org.keycloak.protocol.oidc.OpenIDConnect;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.BruteForceProtector;
 import org.keycloak.services.managers.EventsManager;
@@ -91,8 +91,8 @@ public class RealmsResource {
         EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
         AuthenticationManager authManager = new AuthenticationManager(protector);
 
-        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OpenIDConnect.LOGIN_PROTOCOL);
-        OpenIDConnectService endpoint = (OpenIDConnectService)factory.createProtocolEndpoint(realm, event, authManager);
+        LoginProtocolFactory factory = (LoginProtocolFactory)session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, OIDCLoginProtocol.LOGIN_PROTOCOL);
+        OIDCLoginProtocolService endpoint = (OIDCLoginProtocolService)factory.createProtocolEndpoint(realm, event, authManager);
 
         ResteasyProviderFactory.getInstance().injectProperties(endpoint);
         return endpoint.getLoginStatusIframe(client_id, origin);
@@ -149,7 +149,7 @@ public class RealmsResource {
     protected RealmModel locateRealm(String name, RealmManager realmManager) {
         RealmModel realm = realmManager.getRealmByName(name);
         if (realm == null) {
-            throw new NotFoundException("Realm " + name + " does not exist");
+            throw new NotFoundException("Realm does not exist");
         }
         return realm;
     }
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory b/services/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
index ca8ba63..ce23870 100755
--- a/services/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
+++ b/services/src/main/resources/META-INF/services/org.keycloak.protocol.LoginProtocolFactory
@@ -1 +1 @@
-org.keycloak.protocol.oidc.OpenIDConnectFactory
\ No newline at end of file
+org.keycloak.protocol.oidc.OIDCLoginProtocolFactory
\ No newline at end of file
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
new file mode 100755
index 0000000..0310583
--- /dev/null
+++ b/services/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -0,0 +1 @@
+org.keycloak.protocol.oidc.OIDCAttributeToTokenMapper
\ No newline at end of file
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
index 91c3974..b00bb73 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTest.java
@@ -21,51 +21,16 @@
  */
 package org.keycloak.testsuite.adapter;
 
-import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.Config;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.Version;
-import org.keycloak.constants.AdapterConstants;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
-import org.keycloak.protocol.oidc.TokenManager;
-import org.keycloak.representations.AccessToken;
-import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
-import org.keycloak.services.managers.ResourceAdminManager;
-import org.keycloak.services.resources.admin.AdminRoot;
-import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.KeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testutils.KeycloakServer;
-import org.keycloak.util.BasicAuthHelper;
-import org.openqa.selenium.WebDriver;
-
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-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.net.URI;
+
 import java.net.URL;
 import java.security.PublicKey;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Tests Undertow Adapter
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index e55e0da..08f5775 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -22,7 +22,6 @@
 package org.keycloak.testsuite.adapter;
 
 import org.junit.Assert;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExternalResource;
 import org.keycloak.Config;
@@ -36,16 +35,13 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.admin.AdminRoot;
-import org.keycloak.services.resources.admin.ApplicationsResource;
-import org.keycloak.services.resources.admin.RealmAdminResource;
-import org.keycloak.services.resources.admin.RealmsAdminResource;
 import org.keycloak.testsuite.OAuthClient;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
@@ -96,7 +92,7 @@ public class AdapterTestStrategy extends ExternalResource {
     @WebResource
     protected InputPage inputPage;
 
-    protected String LOGIN_URL = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri(AUTH_SERVER_URL)).build("demo").toString();
+    protected String LOGIN_URL = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri(AUTH_SERVER_URL)).build("demo").toString();
 
     public AdapterTestStrategy(String AUTH_SERVER_URL, String APP_SERVER_BASE_URL, AbstractKeycloakRule keycloakRule) {
         this.AUTH_SERVER_URL = AUTH_SERVER_URL;
@@ -143,7 +139,7 @@ public class AdapterTestStrategy extends ExternalResource {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false);
-            AccessToken token = tm.createClientAccessToken(TokenManager.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(TokenManager.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, null);
             return tm.encodeToken(adminRealm, token);
         } finally {
             keycloakRule.stopSession(session, true);
@@ -168,7 +164,7 @@ public class AdapterTestStrategy extends ExternalResource {
 
         // test logout
 
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
                 .queryParam(OAuth2Constants.REDIRECT_URI, APP_SERVER_BASE_URL + "/customer-portal").build("demo").toString();
         driver.navigate().to(logoutUri);
         Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
@@ -231,7 +227,7 @@ public class AdapterTestStrategy extends ExternalResource {
 
         // test logout
 
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
                 .queryParam(OAuth2Constants.REDIRECT_URI, APP_SERVER_BASE_URL + "/customer-portal").build("demo").toString();
         driver.navigate().to(logoutUri);
         Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
@@ -424,7 +420,7 @@ public class AdapterTestStrategy extends ExternalResource {
     public void testBadUser() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_URL);
-        URI uri = OpenIDConnectService.grantAccessTokenUrl(builder).build("demo");
+        URI uri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("demo");
         WebTarget target = client.target(uri);
         String header = BasicAuthHelper.createHeader("customer-portal", "password");
         Form form = new Form();
@@ -477,7 +473,7 @@ public class AdapterTestStrategy extends ExternalResource {
 
         // test logout
 
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
                 .queryParam(OAuth2Constants.REDIRECT_URI, APP_SERVER_BASE_URL + "/secure-portal").build("demo").toString();
         driver.navigate().to(logoutUri);
         Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
@@ -503,7 +499,7 @@ public class AdapterTestStrategy extends ExternalResource {
             loginAndCheckSession(browser2.driver, browser2.loginPage);
 
             // Logout in browser1
-            String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
+            String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
                     .queryParam(OAuth2Constants.REDIRECT_URI, APP_SERVER_BASE_URL + "/session-portal").build("demo").toString();
             browser1.driver.navigate().to(logoutUri);
             Assert.assertTrue(browser1.driver.getCurrentUrl().startsWith(LOGIN_URL));
@@ -548,7 +544,7 @@ public class AdapterTestStrategy extends ExternalResource {
         loginAndCheckSession(driver, loginPage);
 
         // Logout
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(AUTH_SERVER_URL))
                 .queryParam(OAuth2Constants.REDIRECT_URI, APP_SERVER_BASE_URL + "/session-portal").build("demo").toString();
         driver.navigate().to(logoutUri);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
old mode 100644
new mode 100755
index e384467..54980c6
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
@@ -11,7 +11,7 @@ import org.junit.Test;
 import org.keycloak.constants.AdapterConstants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.OAuthClient;
@@ -31,7 +31,7 @@ import org.openqa.selenium.WebDriver;
  */
 public class CookieTokenStoreAdapterTest {
 
-    public static final String LOGIN_URL = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
+    public static final String LOGIN_URL = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
 
     @ClassRule
     public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenancyTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenancyTest.java
old mode 100644
new mode 100755
index d94914c..8d4b835
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenancyTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/MultiTenancyTest.java
@@ -23,7 +23,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.pages.LoginPage;
@@ -126,7 +126,7 @@ public class MultiTenancyTest {
     }
 
     private void doTenantRequests(String tenant, boolean logout) {
-        String tenantLoginUrl = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build(tenant).toString();
+        String tenantLoginUrl = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build(tenant).toString();
 
         driver.navigate().to("http://localhost:8081/multi-tenant?realm="+tenant);
         System.out.println("Current url: " + driver.getCurrentUrl());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
index 32b34a3..0ebb8fc 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/RelativeUriAdapterTest.java
@@ -32,7 +32,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.idm.RealmRepresentation;
@@ -66,7 +66,7 @@ import java.util.Map;
  */
 public class RelativeUriAdapterTest {
 
-    public static final String LOGIN_URL = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
+    public static final String LOGIN_URL = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
     public static PublicKey realmPublicKey;
     @ClassRule
     public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule(){
@@ -87,7 +87,7 @@ public class RelativeUriAdapterTest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "user", null, "form", false);
-            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, null);
             adminToken = tm.encodeToken(adminRealm, token);
 
         }
@@ -147,7 +147,7 @@ public class RelativeUriAdapterTest {
 
         // test logout
 
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
                 .queryParam(OAuth2Constants.REDIRECT_URI, "/customer-portal").build("demo").toString();
         driver.navigate().to(logoutUri);
         Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
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 2d18dac..0d6c30f 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
@@ -79,7 +79,7 @@ public class AdminAPITest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false);
-            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, null);
             return tm.encodeToken(adminRealm, token);
         } finally {
             keycloakRule.stopSession(session, true);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
index 420d66c..db5d370 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderTest.java
@@ -11,7 +11,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.UsernameLoginFailureModel;
-import org.keycloak.protocol.oidc.OpenIDConnect;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.services.managers.UserManager;
 import org.keycloak.testsuite.rule.KeycloakRule;
 import org.keycloak.util.Time;
@@ -97,7 +97,7 @@ public class UserSessionProviderTest {
         assertEquals(realm.findClient("test-app").getClientId(), session1.getClient().getClientId());
         assertEquals(sessions[0].getId(), session1.getUserSession().getId());
         assertEquals("http://redirect", session1.getRedirectUri());
-        assertEquals("state", session1.getNote(OpenIDConnect.STATE_PARAM));
+        assertEquals("state", session1.getNote(OIDCLoginProtocol.STATE_PARAM));
         assertEquals(2, session1.getRoles().size());
         assertTrue(session1.getRoles().contains("one"));
         assertTrue(session1.getRoles().contains("two"));
@@ -311,7 +311,7 @@ public class UserSessionProviderTest {
                 clientSession.setUserSession(userSession);
                 clientSession.setRedirectUri("http://redirect");
                 clientSession.setRoles(new HashSet<String>());
-                clientSession.setNote(OpenIDConnect.STATE_PARAM, "state");
+                clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, "state");
                 clientSession.setTimestamp(userSession.getStarted());
             }
         } finally {
@@ -404,7 +404,7 @@ public class UserSessionProviderTest {
         ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
         if (userSession != null) clientSession.setUserSession(userSession);
         clientSession.setRedirectUri(redirect);
-        if (state != null) clientSession.setNote(OpenIDConnect.STATE_PARAM, state);
+        if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
         if (roles != null) clientSession.setRoles(roles);
         return clientSession;
     }
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 ed47774..d03cb59 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
@@ -36,7 +36,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.AssertEvents;
@@ -323,10 +323,10 @@ public class AccessTokenTest {
     public void testValidateAccessToken() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OpenIDConnectService.grantAccessTokenUrl(builder).build("test");
+        URI grantUri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("test");
         WebTarget grantTarget = client.target(grantUri);
         builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI validateUri = OpenIDConnectService.validateAccessTokenUrl(builder).build("test");
+        URI validateUri = OIDCLoginProtocolService.validateAccessTokenUrl(builder).build("test");
         WebTarget validateTarget = client.target(validateUri);
 
         {
@@ -354,7 +354,7 @@ public class AccessTokenTest {
         }
         {
             builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-            URI logoutUri = OpenIDConnectService.logoutUrl(builder).build("test");
+            URI logoutUri = OIDCLoginProtocolService.logoutUrl(builder).build("test");
             String header = BasicAuthHelper.createHeader("test-app", "password");
             Form form = new Form();
             form.param("refresh_token", tokenResponse.getRefreshToken());
@@ -380,7 +380,7 @@ public class AccessTokenTest {
     public void testGrantAccessToken() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OpenIDConnectService.grantAccessTokenUrl(builder).build("test");
+        URI grantUri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("test");
         WebTarget grantTarget = client.target(grantUri);
 
         {   // test checkSsl
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
index ca4b7ee..957b66b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/RefreshTokenTest.java
@@ -34,7 +34,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.services.managers.RealmManager;
@@ -97,7 +97,7 @@ public class RefreshTokenTest {
     public void nullRefreshToken() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI uri = OpenIDConnectService.refreshUrl(builder).build("test");
+        URI uri = OIDCLoginProtocolService.refreshUrl(builder).build("test");
         WebTarget target = client.target(uri);
 
         org.keycloak.representations.AccessTokenResponse tokenResponse = null;
@@ -389,10 +389,10 @@ public class RefreshTokenTest {
     public void testCheckSsl() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OpenIDConnectService.grantAccessTokenUrl(builder).build("test");
+        URI grantUri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("test");
         WebTarget grantTarget = client.target(grantUri);
         builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI uri = OpenIDConnectService.refreshUrl(builder).build("test");
+        URI uri = OIDCLoginProtocolService.refreshUrl(builder).build("test");
         WebTarget refreshTarget = client.target(uri);
 
         String refreshToken = null;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index 1625338..a32a70d 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -37,7 +37,7 @@ import org.keycloak.RSATokenVerifier;
 import org.keycloak.VerificationException;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.util.BasicAuthHelper;
@@ -278,7 +278,7 @@ public class OAuthClient {
     }
 
     public void openLogout() {
-        UriBuilder b = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(baseUrl));
         if (redirectUri != null) {
             b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri);
         }
@@ -290,7 +290,7 @@ public class OAuthClient {
     }
 
     public String getLoginFormUrl() {
-        UriBuilder b = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri(baseUrl));
         if (responseType != null) {
             b.queryParam(OAuth2Constants.RESPONSE_TYPE, responseType);
         }
@@ -307,12 +307,12 @@ public class OAuthClient {
     }
 
     public String getAccessTokenUrl() {
-        UriBuilder b = OpenIDConnectService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
     public String getLogoutUrl(String redirectUri, String sessionState) {
-        UriBuilder b = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(baseUrl));
         if (redirectUri != null) {
             b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri);
         }
@@ -323,12 +323,12 @@ public class OAuthClient {
     }
 
     public String getResourceOwnerPasswordCredentialGrantUrl() {
-        UriBuilder b = OpenIDConnectService.grantAccessTokenUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.grantAccessTokenUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
     public String getRefreshTokenUrl() {
-        UriBuilder b = OpenIDConnectService.refreshUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.refreshUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
index 2828f8d..eb52fbb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
@@ -25,7 +25,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.representations.UserInfo;
 import org.keycloak.testsuite.rule.KeycloakRule;
@@ -68,7 +68,7 @@ public class UserInfoTest {
     public void testSuccessfulUserInfoRequest() throws Exception {
         Client client = ClientBuilder.newClient();
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        URI grantUri = OpenIDConnectService.grantAccessTokenUrl(builder).build("test");
+        URI grantUri = OIDCLoginProtocolService.grantAccessTokenUrl(builder).build("test");
         WebTarget grantTarget = client.target(grantUri);
         AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
         Response response = executeUserInfoRequest(accessTokenResponse.getToken());
@@ -117,8 +117,8 @@ public class UserInfoTest {
 
     private Response executeUserInfoRequest(String accessToken) {
         UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
-        UriBuilder uriBuilder = OpenIDConnectService.tokenServiceBaseUrl(builder);
-        URI userInfoUri = uriBuilder.path(OpenIDConnectService.class, "issueUserInfo").build("test");
+        UriBuilder uriBuilder = OIDCLoginProtocolService.tokenServiceBaseUrl(builder);
+        URI userInfoUri = uriBuilder.path(OIDCLoginProtocolService.class, "issueUserInfo").build("test");
         Client client = ClientBuilder.newClient();
         WebTarget userInfoTarget = client.target(userInfoUri);
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
index 599247b..be6d79d 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/perf/AccessTokenPerfTest.java
@@ -34,7 +34,7 @@ import org.junit.ClassRule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.adapters.HttpClientBuilder;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.resources.LoginActionsService;
 import org.keycloak.testsuite.Constants;
 import org.keycloak.testsuite.OAuthClient;
@@ -136,7 +136,7 @@ public class AccessTokenPerfTest {
         }
 
         public String getLoginFormUrl(String state) {
-            UriBuilder b = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri(baseUrl));
+            UriBuilder b = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri(baseUrl));
             if (responseType != null) {
                 b.queryParam(OAuth2Constants.RESPONSE_TYPE, responseType);
             }
@@ -204,7 +204,7 @@ public class AccessTokenPerfTest {
 
             String authorization = BasicAuthHelper.createHeader(clientId, "password");
 
-            String res = client.target(OpenIDConnectService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl)).build(realm)).request()
+            String res = client.target(OIDCLoginProtocolService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl)).build(realm)).request()
                     .header(HttpHeaders.AUTHORIZATION, authorization)
                     .post(Entity.form(form), String.class);
             count.incrementAndGet();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
index 6b73da5..82c0ec9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/saml/SamlBindingTest.java
@@ -247,7 +247,7 @@ public class SamlBindingTest {
             TokenManager tm = new TokenManager();
             UserModel admin = session.users().getUserByUsername("admin", adminRealm);
             UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false);
-            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession);
+            AccessToken token = tm.createClientAccessToken(tm.getAccess(null, adminConsole, admin), adminRealm, adminConsole, admin, userSession, null);
             return tm.encodeToken(adminRealm, token);
         } finally {
             keycloakRule.stopSession(session, true);
diff --git a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
index 6b1a51b..168456e 100755
--- a/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
+++ b/testsuite/performance-web/src/main/java/org/keycloak/testsuite/performance/web/OAuthClient.java
@@ -16,7 +16,7 @@ import org.keycloak.RSATokenVerifier;
 import org.keycloak.VerificationException;
 import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.util.BasicAuthHelper;
@@ -199,7 +199,7 @@ public class OAuthClient {
     }
 
     public String getLoginFormUrl() {
-        UriBuilder b = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri(baseUrl));
         if (responseType != null) {
             b.queryParam(OAuth2Constants.RESPONSE_TYPE, responseType);
         }
@@ -216,12 +216,12 @@ public class OAuthClient {
     }
 
     public String getAccessTokenUrl() {
-        UriBuilder b = OpenIDConnectService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.accessCodeToTokenUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
     public String getLogoutUrl(String redirectUri, String sessionState) {
-        UriBuilder b = OpenIDConnectService.logoutUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(baseUrl));
         if (redirectUri != null) {
             b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri);
         }
@@ -232,12 +232,12 @@ public class OAuthClient {
     }
 
     public String getResourceOwnerPasswordCredentialGrantUrl() {
-        UriBuilder b = OpenIDConnectService.grantAccessTokenUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.grantAccessTokenUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
     public String getRefreshTokenUrl() {
-        UriBuilder b = OpenIDConnectService.refreshUrl(UriBuilder.fromUri(baseUrl));
+        UriBuilder b = OIDCLoginProtocolService.refreshUrl(UriBuilder.fromUri(baseUrl));
         return b.build(realm).toString();
     }
 
diff --git a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java b/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
index c6e3698..7443287 100755
--- a/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
+++ b/testsuite/proxy/src/test/java/org/keycloak/testsuite/ProxyTest.java
@@ -22,15 +22,6 @@
 package org.keycloak.testsuite;
 
 import io.undertow.Undertow;
-import io.undertow.io.IoCallback;
-import io.undertow.security.api.SecurityContext;
-import io.undertow.server.HttpHandler;
-import io.undertow.server.HttpServerExchange;
-import io.undertow.server.handlers.ResponseCodeHandler;
-import io.undertow.server.handlers.proxy.ProxyHandler;
-import io.undertow.server.handlers.proxy.SimpleProxyClientProvider;
-import io.undertow.util.Headers;
-import io.undertow.util.HttpString;
 import org.apache.catalina.startup.Tomcat;
 import org.junit.AfterClass;
 import org.junit.Assert;
@@ -39,16 +30,11 @@ import org.junit.ClassRule;
 import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.KeycloakSecurityContext;
 import org.keycloak.OAuth2Constants;
-import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.undertow.AbstractUndertowRequestAuthenticator;
-import org.keycloak.adapters.undertow.UndertowHttpFacade;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.proxy.ProxyServerBuilder;
-import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.pages.LoginPage;
@@ -72,15 +58,13 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.net.URI;
 import java.net.URL;
-import java.security.Principal;
 import java.util.Enumeration;
 import java.util.regex.Matcher;
 
 @Ignore
 public class ProxyTest {
-    static String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
+    static String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
             .queryParam(OAuth2Constants.REDIRECT_URI, "http://localhost:8080/customer-portal").build("demo").toString();
 
     @ClassRule
@@ -204,7 +188,7 @@ public class ProxyTest {
     @WebResource
     protected LoginPage loginPage;
 
-    public static final String LOGIN_URL = OpenIDConnectService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
+    public static final String LOGIN_URL = OIDCLoginProtocolService.loginPageUrl(UriBuilder.fromUri("http://localhost:8081/auth")).build("demo").toString();
 
     @Test
     public void testHttp() throws Exception {
@@ -261,7 +245,7 @@ public class ProxyTest {
 
         // test logout
 
-        String logoutUri = OpenIDConnectService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
+        String logoutUri = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri("http://localhost:8081/auth"))
                 .queryParam(OAuth2Constants.REDIRECT_URI, baseUrl + "/customer-portal/users").build("demo").toString();
         driver.navigate().to(logoutUri);
         Assert.assertTrue(driver.getCurrentUrl().startsWith(LOGIN_URL));
diff --git a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatTest.java b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatTest.java
index 076daaf..9809e09 100755
--- a/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatTest.java
+++ b/testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatTest.java
@@ -22,37 +22,18 @@
 package org.keycloak.testsuite;
 
 import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.OAuth2Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
-import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.adapter.AdapterTestStrategy;
-import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testutils.KeycloakServer;
-import org.openqa.selenium.WebDriver;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.UriBuilder;
+
 import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
 import java.net.URL;
-import java.security.Principal;
 import java.util.regex.Matcher;
 
 /**
diff --git a/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java b/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java
index 0039f4e..ef06a17 100755
--- a/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java
+++ b/testsuite/tomcat7/src/test/java/org/keycloak/testsuite/Tomcat7Test.java
@@ -23,37 +23,18 @@ package org.keycloak.testsuite;
 
 import org.apache.catalina.startup.Tomcat;
 import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.OAuth2Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
-import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.adapter.AdapterTestStrategy;
-import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testutils.KeycloakServer;
-import org.openqa.selenium.WebDriver;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.UriBuilder;
+
 import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
 import java.net.URL;
-import java.security.Principal;
 import java.util.regex.Matcher;
 
 /**
diff --git a/testsuite/tomcat8/src/test/java/org/keycloak/testsuite/TomcatTest.java b/testsuite/tomcat8/src/test/java/org/keycloak/testsuite/TomcatTest.java
index 2b03b82..86fcac0 100755
--- a/testsuite/tomcat8/src/test/java/org/keycloak/testsuite/TomcatTest.java
+++ b/testsuite/tomcat8/src/test/java/org/keycloak/testsuite/TomcatTest.java
@@ -23,37 +23,18 @@ package org.keycloak.testsuite;
 
 import org.apache.catalina.startup.Tomcat;
 import org.junit.AfterClass;
-import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
-import org.keycloak.KeycloakSecurityContext;
-import org.keycloak.OAuth2Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.protocol.oidc.OpenIDConnectService;
-import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.adapter.AdapterTestStrategy;
-import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
-import org.keycloak.testsuite.rule.WebResource;
-import org.keycloak.testsuite.rule.WebRule;
-import org.keycloak.testutils.KeycloakServer;
-import org.openqa.selenium.WebDriver;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.UriBuilder;
+
 import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
 import java.net.URL;
-import java.security.Principal;
 import java.util.regex.Matcher;
 
 /**