keycloak-uncached

Merge pull request #1176 from mposolda/master KEYCLOAK-1070

4/23/2015 2:01:37 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 b4d93a7..83eadb5 100755
--- a/connections/jpa/src/main/resources/META-INF/persistence.xml
+++ b/connections/jpa/src/main/resources/META-INF/persistence.xml
@@ -27,6 +27,7 @@
         <!-- JpaUserSessionProvider -->
         <class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
         <class>org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity</class>
+        <class>org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity</class>
         <class>org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity</class>
         <class>org.keycloak.models.sessions.jpa.entities.UserSessionNoteEntity</class>
         <class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
index 7b8c877..f435ffc 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.2.0.RC1.xml
@@ -62,28 +62,40 @@
                 <constraints nullable="false"/>
             </column>
         </createTable>
+        <createTable tableName="CLIENT_SESSION_PROT_MAPPER">
+            <column name="PROTOCOL_MAPPER_ID" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+            <column name="CLIENT_SESSION" type="VARCHAR(36)">
+                <constraints nullable="false"/>
+            </column>
+        </createTable>
         <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_IDPM" tableName="IDENTITY_PROVIDER_MAPPER"/>
         <addPrimaryKey columnNames="IDP_MAPPER_ID, NAME" constraintName="CONSTRAINT_IDPMConfig" tableName="IDP_MAPPER_CONFIG"/>
         <addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GRNTCSNT_PM" tableName="USER_CONSENT"/>
         <addPrimaryKey columnNames="USER_CONSENT_ID, ROLE_ID" constraintName="CONSTRAINT_GRNTCSNT_ROLE_PM" tableName="USER_CONSENT_ROLE"/>
         <addPrimaryKey columnNames="USER_CONSENT_ID, PROTOCOL_MAPPER_ID" constraintName="CONSTRAINT_GRNTCSNT_PRM_PM" tableName="USER_CONSENT_PROT_MAPPER"/>
+        <addPrimaryKey columnNames="CLIENT_SESSION, PROTOCOL_MAPPER_ID" constraintName="CONSTRAINT_CS_PMP_PK" tableName="CLIENT_SESSION_PROT_MAPPER"/>
         <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="IDENTITY_PROVIDER_MAPPER" constraintName="FK_IDPM_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
         <addForeignKeyConstraint baseColumnNames="IDP_MAPPER_ID" baseTableName="IDP_MAPPER_CONFIG" constraintName="FK_IDPMConfig" referencedColumnNames="ID" referencedTableName="IDENTITY_PROVIDER_MAPPER"/>
         <addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_CONSENT" constraintName="FK_GRNTCSNT_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
         <addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_ROLE" constraintName="FK_GRNTCSNT_ROLE_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
         <addForeignKeyConstraint baseColumnNames="USER_CONSENT_ID" baseTableName="USER_CONSENT_PROT_MAPPER" constraintName="FK_GRNTCSNT_PRM_GR" referencedColumnNames="ID" referencedTableName="USER_CONSENT"/>
+        <addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_SESSION_PROT_MAPPER" constraintName="FK_33A8SGQW18I532811V7O2DK89" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
 
+        <renameColumn tableName="CLIENT" newColumnName="CLIENT_ID" oldColumnName="NAME"/>
         <addColumn tableName="CLIENT">
             <column name="CONSENT_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
                 <constraints nullable="false"/>
             </column>
+            <column name="NAME" type="VARCHAR(255)" />
         </addColumn>
         <update tableName="CLIENT">
             <column name="CONSENT_REQUIRED" valueBoolean="true"/>
             <where>DTYPE = 'OAuthClientEntity'</where>
         </update>
         <dropColumn tableName="CLIENT" columnName="DTYPE"/>
-        <renameColumn tableName="CLIENT" newColumnName="CLIENT_ID" oldColumnName="NAME"/>
+
         <renameColumn tableName="REALM" newColumnName="MASTER_ADMIN_CLIENT" oldColumnName="MASTER_ADMIN_APP"/>
 
         <renameTable oldTableName="REALM_APPLICATION" newTableName="REALM_CLIENT"/>
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index 0ef0069..d591fba 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -39,6 +39,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
             "org.keycloak.models.sessions.mongo.entities.MongoClientSessionEntity",
             "org.keycloak.models.entities.UserFederationProviderEntity",
             "org.keycloak.models.entities.ProtocolMapperEntity",
+            "org.keycloak.models.entities.IdentityProviderMapperEntity",
             "org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity"
     };
 
diff --git a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
index 8ee4db3..811039c 100644
--- a/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
+++ b/connections/mongo-update/src/main/java/org/keycloak/connections/mongo/updater/impl/updates/Update1_2_0_RC1.java
@@ -17,6 +17,9 @@ public class Update1_2_0_RC1 extends Update {
 
     @Override
     public void update(KeycloakSession session) {
+        deleteEntries("clientSessions");
+        deleteEntries("sessions");
+
         convertApplicationsToClients();
         convertOAuthClientsToClients();
 
diff --git a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
index de40f10..4137196 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ClientRepresentation.java
@@ -10,6 +10,7 @@ import java.util.Map;
 public class ClientRepresentation {
     protected String id;
     protected String clientId;
+    protected String name;
     protected String adminUrl;
     protected String baseUrl;
     protected Boolean surrogateAuthRequired;
@@ -40,6 +41,14 @@ public class ClientRepresentation {
         this.id = id;
     }
 
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
     public String getClientId() {
         return clientId;
     }
diff --git a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
index 66b106c..fbd909d 100755
--- a/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
+++ b/export-import/export-import-api/src/main/java/org/keycloak/exportimport/util/ImportUtils.java
@@ -120,6 +120,8 @@ public class ImportUtils {
         adminRole.setDescription("${role_"+AdminRoles.ADMIN+"}");
 
         ClientModel realmAdminApp = KeycloakModelUtils.createClient(adminRealm, KeycloakModelUtils.getMasterRealmAdminApplicationClientId(realm));
+        // No localized name for now
+        realmAdminApp.setName(realm.getName() + " Realm");
         realmAdminApp.setBearerOnly(true);
         realm.setMasterAdminClient(realmAdminApp);
 
diff --git a/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java b/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java
index 3e236dd..257fc84 100644
--- a/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java
+++ b/forms/account-api/src/main/java/org/keycloak/account/AccountPages.java
@@ -5,6 +5,6 @@ package org.keycloak.account;
  */
 public enum AccountPages {
 
-    ACCOUNT, PASSWORD, TOTP, FEDERATED_IDENTITY, LOG, SESSIONS, ACCESS;
+    ACCOUNT, PASSWORD, TOTP, FEDERATED_IDENTITY, LOG, SESSIONS, APPLICATIONS;
 
 }
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
index ba95348..ab1dcad 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccountProvider.java
@@ -20,7 +20,7 @@ import javax.ws.rs.core.UriInfo;
 import org.jboss.logging.Logger;
 import org.keycloak.account.AccountPages;
 import org.keycloak.account.AccountProvider;
-import org.keycloak.account.freemarker.model.AccessBean;
+import org.keycloak.account.freemarker.model.ConsentBean;
 import org.keycloak.account.freemarker.model.AccountBean;
 import org.keycloak.account.freemarker.model.AccountFederatedIdentityBean;
 import org.keycloak.account.freemarker.model.FeaturesBean;
@@ -185,8 +185,8 @@ public class FreeMarkerAccountProvider implements AccountProvider {
             case SESSIONS:
                 attributes.put("sessions", new SessionsBean(realm, sessions));
                 break;
-            case ACCESS:
-                attributes.put("access", new AccessBean(realm, user, uriInfo.getBaseUri(), stateChecker));
+            case APPLICATIONS:
+                attributes.put("consent", new ConsentBean(user));
                 attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle));
                 break;
             case PASSWORD:
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
index 40ea59f..0de3a9a 100755
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
@@ -27,8 +27,8 @@ public class UrlBean {
         this.stateChecker = stateChecker;
     }
 
-    public String getAccessUrl() {
-        return Urls.accountAccessPage(baseQueryURI, realm).toString();
+    public String getApplicationsUrl() {
+        return Urls.accountApplicationsPage(baseQueryURI, realm).toString();
     }
 
     public String getAccountUrl() {
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java
index 847a3e6..d3116f6 100644
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/Templates.java
@@ -21,8 +21,8 @@ public class Templates {
                 return "log.ftl";
             case SESSIONS:
                 return "sessions.ftl";
-            case ACCESS:
-                return "access.ftl";
+            case APPLICATIONS:
+                return "applications.ftl";
             default:
                 throw new IllegalArgumentException();
         }
diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties
index a846d54..add9daa 100644
--- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_de.properties
@@ -16,16 +16,40 @@ authenticatorTitle=Authenticator
 authenticatorCode=One-time code
 email=E-Mail
 firstName=Vorname
+givenName=Vorname
+fullName=voller Name
 lastName=Nachname
+familyName=Nachname
 password=Passwort
 passwordConfirm=Passwortbest\u00E4tigung
 passwordNew=Neues Passwort
 username=Benutzernamen
+address=Adresse
 street=Strasse
 region=Staat, Provinz, Region
 postal_code=PLZ
 locality=Stadt oder Ortschaft
 country=Land
+emailVerified=E-Mail verifiziert
+gssDelegationCredential=GSS delegierte Berechtigung
+
+role_admin=Admin
+role_realm-admin=Realm Admin
+role_create-realm=Realm erstellen
+role_view-realm=Realm ansehen
+role_view-users=Benutzer ansehen
+role_view-applications=Applicationen ansehen
+role_view-clients=Clients ansehen
+role_view-events=Events ansehen
+role_view-identity-providers=Identity Providers ansehen
+role_manage-realm=Realm verwalten
+role_manage-users=Benutzer verwalten
+role_manage-applications=Applikationen verwalten
+role_manage-identity-providers=Identity Provider verwalten
+role_manage-clients=Clients verwalten
+role_manage-events=Events verwalten
+role_view-profile=Profile ansehen
+role_manage-account=Profile verwalten
 
 requiredFields=Erforderliche Felder
 allFieldsRequired=Alle Felder sind Erforderlich
@@ -42,7 +66,7 @@ details=Details
 started=Startdatum
 lastAccess=Letzter Zugriff
 expires=Ablaufdatum
-applications=
+applications=Applicationen
 
 account=Benutzerkonto
 federatedIdentity=Federated Identity
diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties
index d0bbb37..a2d99fe 100755
--- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_en.properties
@@ -12,7 +12,7 @@ changePasswordHtmlTitle=Change Password
 sessionsHtmlTitle=Sessions
 accountManagementTitle=Keycloak Account Management
 authenticatorTitle=Authenticator
-accessHtmlTitle=Manage Granted Permissions
+applicationsHtmlTitle=Manage Granted Permissions
 
 authenticatorCode=One-time code
 email=Email
@@ -50,6 +50,9 @@ role_manage-identity-providers=Manage identity providers
 role_manage-clients=Manage clients
 role_manage-events=Manage events
 role_view-profile=View profile
+client_account=Account
+client_security-admin-console=Security Admin Console
+client_realm-management=Realm Management
 
 
 requiredFields=Required fields
@@ -74,13 +77,12 @@ federatedIdentity=Federated Identity
 authenticator=Authenticator
 sessions=Sessions
 log=Log
-access=Access
 
 grantedPersonalInfo=Granted Personal Info
 grantedPermissions=Granted Permissions
 action=Action
-inResource=in <strong>{0}</strong>
-revoke=Revoke Access
+inResource=in
+revoke=Revoke Grant
 
 configureAuthenticators=Configured Authenticators
 mobile=Mobile
@@ -106,7 +108,7 @@ readOnlyPasswordMessage=You can''t update your password as your account is read 
 successTotpMessage=Mobile authenticator configured.
 successTotpRemovedMessage=Mobile authenticator removed.
 
-successGrantRevokedMessage=Access revoked successfully.
+successGrantRevokedMessage=Grant revoked successfully.
 
 accountUpdatedMessage=Your account has been updated.
 accountPasswordUpdatedMessage=Your password has been updated.
diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties
index d22b935..99eff0c 100755
--- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties
+++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_it.properties
@@ -16,16 +16,40 @@ authenticatorTitle=Authenticator
 authenticatorCode=Codice One-time
 email=Email
 firstName=Nome
+givenName=Nome
+fullName=Nome Completo
 lastName=Cognome
+familyName=Cognome
 password=Password
 passwordConfirm=Conferma Password
 passwordNew=Nuova Password
 username=Username
+address=Indirizzo
 street=Via
 locality=Citta'' o Localita''
 region=Stato, Provincia, o Regione
 postal_code=Cap
 country=Paese
+emailVerified=Email verificata
+gssDelegationCredential=credenziali gss delegation
+
+role_admin=Admin
+role_realm-admin=Realm Admin
+role_create-realm=Crea realm
+role_view-realm=Visualizza realm
+role_view-users=Visualizza utenti
+role_view-applications=Visualizza applicazioni
+role_view-clients=Visualizza client
+role_view-events=Visualizza eventi
+role_view-identity-providers=Visualizza identity provider
+role_manage-realm=Gestisci realm
+role_manage-users=Gestisci utenti
+role_manage-applications=Gestisci applicazioni
+role_manage-identity-providers=Gestisci identity provider
+role_manage-clients=Gestisci client
+role_manage-events=Gestisci eventi
+role_view-profile=Visualizza profilo
+role_manage-account=Gestisci account
 
 requiredFields=Campi obbligatori
 allFieldsRequired=Tutti campi obbligatori
diff --git a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties
index 367be5f..a29d60d 100644
--- a/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties
+++ b/forms/common-themes/src/main/resources/theme/base/account/messages/messages_pt_BR.properties
@@ -16,16 +16,40 @@ authenticatorTitle=Autenticator
 authenticatorCode=C\u00F3digo autenticador
 email=Email
 firstName=Primeiro nome
+givenName=Primeiro nome
+fullName=Nome completo
 lastName=Sobrenome
+familyName=Sobrenome
 password=Senha
 passwordConfirm=Confirma\u00E7\u00E3o
 passwordNew=Nova senha
 username=Nome de us\u00FAario
+address=Endere\u00E7o
 street=Logradouro
 locality=Cidade ou Localidade
 region=Estado
 postal_code=CEP
 country=Pa\u00EDs
+emailVerified=Email verificado
+gssDelegationCredential=gss delega\u00E7\u00E3o credencial
+
+role_admin=Admin
+role_realm-admin=Realm Admin
+role_create-realm=Cria realm
+role_view-realm=Visualiza realm
+role_view-users=Visualiza usu\u00E1rios
+role_view-applications=Visualiza aplica\u00E7\u00F5es
+role_view-clients=Visualiza clientes
+role_view-events=Visualiza eventos
+role_view-identity-providers=Visualiza provedores de identidade
+role_manage-realm=Gerencia realm
+role_manage-users=Gerencia usu\u00E1rios
+role_manage-applications=Gerencia aplica\u00E7\u00F5es
+role_manage-identity-providers=Gerencia provedores de identidade
+role_manage-clients=Gerencia clientes
+role_manage-events=Gerencia eventos
+role_view-profile=Visualiza perfil
+role_manage-account=Gerencia contas
 
 requiredFields=Campos obrigat\u00F3rios
 allFieldsRequired=Todos os campos s\u00E3o obrigat\u00F3rios
diff --git a/forms/common-themes/src/main/resources/theme/base/account/template.ftl b/forms/common-themes/src/main/resources/theme/base/account/template.ftl
index 1319b6f..dfd2b29 100644
--- a/forms/common-themes/src/main/resources/theme/base/account/template.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/account/template.ftl
@@ -56,7 +56,7 @@
                 <li class="<#if active=='totp'>active</#if>"><a href="${url.totpUrl}">${msg("authenticator")}</a></li>
                 <#if features.identityFederation><li class="<#if active=='social'>active</#if>"><a href="${url.socialUrl}">${msg("federatedIdentity")}</a></li></#if>
                 <li class="<#if active=='sessions'>active</#if>"><a href="${url.sessionsUrl}">${msg("sessions")}</a></li>
-                <li class="<#if active=='access'>active</#if>"><a href="${url.accessUrl}">${msg("access")}</a></li>
+                <li class="<#if active=='applications'>active</#if>"><a href="${url.applicationsUrl}">${msg("applications")}</a></li>
                 <#if features.log><li class="<#if active=='log'>active</#if>"><a href="${url.logUrl}">${msg("log")}</a></li></#if>
             </ul>
         </div>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index ebfca94..69dd012 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -19,9 +19,17 @@
             <fieldset class="border-top">
                 <div class="form-group">
                     <label class="col-sm-2 control-label" for="clientId">Client ID <span class="required" data-ng-show="create">*</span></label>
-                    <div class="col-sm-4">
+                    <div class="col-sm-6">
                         <input class="form-control" type="text" id="clientId" name="clientId" data-ng-model="client.clientId" autofocus required>
                     </div>
+                    <span tooltip-placement="right" tooltip="Specifies ID referenced in URI and tokens. For example 'my-client'" class="fa fa-info-circle"></span>
+                </div>
+                <div class="form-group">
+                    <label class="col-sm-2 control-label" for="name">Name </label>
+                    <div class="col-sm-6">
+                        <input class="form-control" type="text" id="name" name="name" data-ng-model="client.name" autofocus>
+                    </div>
+                    <span tooltip-placement="right" tooltip="Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}" class="fa fa-info-circle"></span>
                 </div>
                 <div class="form-group clearfix block">
                     <label class="col-sm-2 control-label" for="enabled">Enabled</label>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl
index 6136e8b..30d55c3 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl
@@ -3,7 +3,7 @@
     <#if section = "title">
         ${msg("oauthGrantTitle")}
     <#elseif section = "header">
-        ${msg("oauthGrantTitleHtml",(realm.name!''), (client.clientId!''))}
+        ${msg("oauthGrantTitleHtml",(realm.name!''))} <strong><#if client.name??>${advancedMsg(client.name)}<#else>${client.clientId}</#if></strong>.
     <#elseif section = "form">
         <div id="kc-oauth" class="content-area">
             <h3>${msg("oauthGrantRequest")}</h3>
@@ -34,10 +34,10 @@
                 </#if>
                 <#if oauth.resourceRolesRequested??>
                     <#list oauth.resourceRolesRequested?keys as resource>
-                        <#list oauth.resourceRolesRequested[resource] as role>
+                        <#list oauth.resourceRolesRequested[resource] as clientRole>
                             <li>
-                                <span class="kc-role"><#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)}</#if></span>
-                                <span class="kc-resource">${msg("inResource", resource)}</span>
+                                <span class="kc-role"><#if clientRole.roleDescription??>${advancedMsg(clientRole.roleDescription)}<#else>${advancedMsg(clientRole.roleName)}</#if></span>
+                                <span class="kc-resource">${msg("inResource")} <strong><#if clientRole.clientName??>${advancedMsg(clientRole.clientName)}<#else>${clientRole.clientId}</#if></strong> </span>
                             </li>
                         </#list>
                     </#list>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
index ca45f53..5999681 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
@@ -16,7 +16,7 @@ loginOauthTitleHtml=Tempor\u00E4rer zugriff auf <strong>{0}</strong> angefordert
 loginTotpTitle=Mobile Authentifizierung Einrichten
 loginProfileTitle=Benutzerkonto Informationen aktualisieren
 oauthGrantTitle=OAuth gew\u00E4hren
-oauthGrantTitleHtml=Tempor\u00E4rer zugriff auf <strong>{0}</strong> angefordert von <strong>{1}</strong>.
+oauthGrantTitleHtml=Tempor\u00E4rer zugriff auf <strong>{0}</strong> angefordert von
 errorTitle=Es tut uns leid...
 errorTitleHtml=Es tut uns leid...
 emailVerifyTitle=E-Mail verifizieren
@@ -55,7 +55,7 @@ loginTotpStep3=Geben Sie den One-time Code welcher die Applikation generiert hat
 loginTotpOneTime=One-time Code
 
 oauthGrantRequest=Wollen Sie diese Zugriffsreche gew\u00E4hren?
-inResource=in <strong>{0}</strong>
+inResource=in
 
 emailVerifyInstruction1=Ein E-Mail mit weitern Anweisungen wurde an Sie versendet.
 emailVerifyInstruction2=Falls Sie kein E-Mail erhalten haben, dann k\u00F6nnen Sie
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
index 006883f..a1f76ee 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -14,7 +14,7 @@ loginTitleHtml=Log in to <strong>{0}</strong>
 loginTotpTitle=Mobile Authenticator Setup
 loginProfileTitle=Update Account Information
 oauthGrantTitle=OAuth Grant
-oauthGrantTitleHtml=Temporary access for <strong>{0}</strong> requested by <strong>{1}</strong>.
+oauthGrantTitleHtml=Temporary access for <strong>{0}</strong> requested by
 errorTitle=We''re sorry...
 errorTitleHtml=We''re <strong>sorry</strong> ...
 emailVerifyTitle=Email verification
@@ -45,7 +45,7 @@ region=State, Province, or Region
 postal_code=Zip or Postal code
 country=Country
 emailVerified=Email verified
-gssDelegationCredential=gss delegation credential
+gssDelegationCredential=GSS Delegation Credential
 
 loginTotpStep1=Install <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> or Google Authenticator on your mobile. Both applications are available in <a href="https://play.google.com">Google Play</a> and Apple App Store.
 loginTotpStep2=Open the application and scan the barcode or enter the key
@@ -53,7 +53,7 @@ loginTotpStep3=Enter the one-time code provided by the application and click Sub
 loginTotpOneTime=One-time code
 
 oauthGrantRequest=Do you grant these access privileges?
-inResource=in <strong>{0}</strong>
+inResource=in
 
 emailVerifyInstruction1=An email with instructions to verify your email address has been sent to you.
 emailVerifyInstruction2=Haven''t received a verification code in your email?
@@ -84,6 +84,9 @@ role_manage-clients=Manage clients
 role_manage-events=Manage events
 role_view-profile=View profile
 role_manage-account=Manage account
+client_account=Account
+client_security-admin-console=Security Admin Console
+client_realm-management=Realm Management
 
 invalidUserMessage=Invalid username or password.
 invalidEmailMessage=Invalid email address.
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
index f7296b9..b019d6c 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_it.properties
@@ -14,7 +14,7 @@ loginTitleHtml=Accedi a <strong>{0}</strong>
 loginTotpTitle=Configura Autenticazione Mobile
 loginProfileTitle=Aggiorna Profilo
 oauthGrantTitle=OAuth Grant
-oauthGrantTitleHtml=Accesso temporaneo per <strong>{0}</strong> richiesto da <strong>{1}</strong>.
+oauthGrantTitleHtml=Accesso temporaneo per <strong>{0}</strong> richiesto da
 errorTitle=Siamo spiacenti...
 errorTitleHtml=Siamo <strong>spiacenti</strong> ...
 emailVerifyTitle=Verifica Email
@@ -53,7 +53,7 @@ loginTotpStep3=Scrivi il codice one-time fornito dall''applicazione e premi Invi
 loginTotpOneTime=Codice one-time
 
 oauthGrantRequest=Vuoi assegnare questi privilegi di accesso?
-inResource=per <strong>{0}</strong>
+inResource=per
 
 emailVerifyInstruction1=Ti e'' stata inviata una email con le istruzioni per la verifica della tua email.
 emailVerifyInstruction2=Non hai ricevuto un codice di verifica nella tua email?
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
index 896f83f..8d50d3e 100644
--- a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_pt_BR.properties
@@ -14,7 +14,7 @@ loginTitleHtml=Entrar em <strong>{0}</strong>
 loginTotpTitle=Configura\u00E7\u00E3o do autenticador mobile
 loginProfileTitle=Atualiza\u00E7\u00E3o de Informa\u00E7\u00F5es da Conta
 oauthGrantTitle=Concess\u00E3o OAuth
-oauthGrantTitleHtml=Acesso tempor\u00E1rio para <strong>{0}</strong> solicitado pela <strong>{1}</strong>.
+oauthGrantTitleHtml=Acesso tempor\u00E1rio para <strong>{0}</strong> solicitado pela
 errorTitle=N\u00F3s lamentamos...
 errorTitleHtml=N\u00F3s <strong>lamentamos</strong> ...
 emailVerifyTitle=Verifica\u00E7\u00E3o de e-mail
@@ -53,7 +53,7 @@ loginTotpStep3=Digite o c\u00F3digo fornecido pelo aplicativo e clique em Enviar
 loginTotpOneTime=C\u00F3digo autenticador
 
 oauthGrantRequest=Voc\u00EA concede esses privil\u00E9gios de acesso?
-inResource=em <strong>{0}</strong>
+inResource=em
 
 emailVerifyInstruction1=Um e-mail com instru\u00E7\u00F5es para verificar o seu endere\u00E7o de e-mail foi enviado para voc\u00EA.
 emailVerifyInstruction2=Voc\u00EA n\u00E3o recebeu um c\u00F3digo de verifica\u00E7\u00E3o em seu e-mail?
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
index 53f7937..d945c38 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/ClientBean.java
@@ -18,6 +18,10 @@ public class ClientBean {
         return client.getClientId();
     }
 
+    public String getName() {
+        return client.getName();
+    }
+
     public String getBaseUrl() {
         return client.getBaseUrl();
     }
diff --git a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
index 98cd164..6032587 100755
--- a/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
+++ b/forms/login-freemarker/src/main/java/org/keycloak/login/freemarker/model/OAuthGrantBean.java
@@ -21,6 +21,7 @@
  */
 package org.keycloak.login.freemarker.model;
 
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.ProtocolMapperModel;
@@ -29,6 +30,7 @@ import org.keycloak.models.RoleModel;
 import javax.ws.rs.core.MultivaluedMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
@@ -37,7 +39,7 @@ public class OAuthGrantBean {
 
     private final String accessRequestMessage;
     private List<RoleModel> realmRolesRequested;
-    private MultivaluedMap<String, RoleModel> resourceRolesRequested;
+    private MultivaluedMap<String, ClientRoleEntry> resourceRolesRequested;
     private String code;
     private ClientModel client;
     private List<String> claimsRequested;
@@ -47,7 +49,17 @@ public class OAuthGrantBean {
         this.code = code;
         this.client = client;
         this.realmRolesRequested = realmRolesRequested;
-        this.resourceRolesRequested = resourceRolesRequested;
+        if (resourceRolesRequested != null) {
+            this.resourceRolesRequested = new MultivaluedMapImpl<String, ClientRoleEntry>();
+            for (List<RoleModel> clientRoles : resourceRolesRequested.values()) {
+                for (RoleModel role : clientRoles) {
+                    ClientModel currentClient = (ClientModel) role.getContainer();
+                    ClientRoleEntry roleEntry = new ClientRoleEntry(currentClient.getClientId(), currentClient.getName(), role.getName(), role.getDescription());
+                    this.resourceRolesRequested.add(currentClient.getClientId(), roleEntry);
+                }
+            }
+        }
+
         this.accessRequestMessage = accessRequestMessage;
 
         List<String> claims = new LinkedList<String>();
@@ -63,7 +75,7 @@ public class OAuthGrantBean {
         return code;
     }
 
-    public MultivaluedMap<String, RoleModel> getResourceRolesRequested() {
+    public MultivaluedMap<String, ClientRoleEntry> getResourceRolesRequested() {
         return resourceRolesRequested;
     }
 
@@ -82,4 +94,36 @@ public class OAuthGrantBean {
     public String getAccessRequestMessage() {
         return this.accessRequestMessage;
     }
+
+    // Same class used in ConsentBean in account as well. Maybe should be merged into common-freemarker...
+    public static class ClientRoleEntry {
+
+        private final String clientId;
+        private final String clientName;
+        private final String roleName;
+        private final String roleDescription;
+
+        public ClientRoleEntry(String clientId, String clientName, String roleName, String roleDescription) {
+            this.clientId = clientId;
+            this.clientName = clientName;
+            this.roleName = roleName;
+            this.roleDescription = roleDescription;
+        }
+
+        public String getClientId() {
+            return clientId;
+        }
+
+        public String getClientName() {
+            return clientName;
+        }
+
+        public String getRoleName() {
+            return roleName;
+        }
+
+        public String getRoleDescription() {
+            return roleDescription;
+        }
+    }
 }
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 2382f55..5fae169 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientModel.java
@@ -24,6 +24,10 @@ public interface ClientModel extends RoleContainerModel {
 
     void setClientId(String clientId);
 
+    String getName();
+
+    void setName(String name);
+
     boolean isEnabled();
 
     void setEnabled(boolean enabled);
diff --git a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
index 059afc9..7c197a3 100755
--- a/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
+++ b/model/api/src/main/java/org/keycloak/models/ClientSessionModel.java
@@ -28,6 +28,9 @@ public interface ClientSessionModel {
     public Set<String> getRoles();
     public void setRoles(Set<String> roles);
 
+    public Set<String> getProtocolMappers();
+    public void setProtocolMappers(Set<String> protocolMappers);
+
     /**
      * Authentication request type, i.e. OAUTH, SAML 2.0, SAML 1.1, etc.
      *
diff --git a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
index 699c6d6..513c4ef 100644
--- a/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
+++ b/model/api/src/main/java/org/keycloak/models/entities/ClientEntity.java
@@ -11,6 +11,7 @@ import java.util.Map;
 public class ClientEntity extends AbstractIdentifiableEntity {
 
     private String clientId;
+    private String name;
     private String realmId;
     private boolean enabled;
     private String secret;
@@ -49,6 +50,14 @@ public class ClientEntity extends AbstractIdentifiableEntity {
         this.clientId = clientId;
     }
 
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
     public boolean isEnabled() {
         return enabled;
     }
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 17c88ea..9c29604 100755
--- a/model/api/src/main/java/org/keycloak/models/RealmModel.java
+++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java
@@ -145,6 +145,7 @@ public interface RealmModel extends RoleContainerModel {
 
     void updateDefaultRoles(String[] defaultRoles);
 
+    // Key is clientId
     Map<String, ClientModel> getClientNameMap();
 
     List<ClientModel> getClients();
diff --git a/model/api/src/main/java/org/keycloak/models/UserConsentModel.java b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java
index 11f1034..a8e4cc3 100644
--- a/model/api/src/main/java/org/keycloak/models/UserConsentModel.java
+++ b/model/api/src/main/java/org/keycloak/models/UserConsentModel.java
@@ -8,31 +8,20 @@ import java.util.Set;
  */
 public class UserConsentModel {
 
-    private final RealmModel realm;
     private final ClientModel client;
     private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
     private Set<RoleModel> roles = new HashSet<RoleModel>();
 
-    public UserConsentModel(RealmModel realm, String clientId) {
-        this.realm = realm;
-        this.client = realm.getClientById(clientId);
-
-        if (client == null) {
-            throw new ModelException("Client with id [" + clientId + "] is not available");
-        }
+    public UserConsentModel(ClientModel client) {
+        this.client = client;
     }
 
     public ClientModel getClient() {
         return client;
     }
 
-    public void addGrantedRole(String roleId) {
-        RoleModel role = realm.getRoleById(roleId);
-
-        // Chance that role was already deleted by other transaction and is not available anymore
-        if (role != null) {
-            roles.add(role);
-        }
+    public void addGrantedRole(RoleModel role) {
+        roles.add(role);
     }
 
     public Set<RoleModel> getGrantedRoles() {
@@ -46,13 +35,8 @@ public class UserConsentModel {
         return false;
     }
 
-    public void addGrantedProtocolMapper(String protocolMapperId) {
-        ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protocolMapperId);
-
-        // Chance that protocolMapper was already deleted by other transaction and is not available anymore
-        if (protocolMapper != null) {
-            protocolMappers.add(protocolMapper);
-        }
+    public void addGrantedProtocolMapper(ProtocolMapperModel protocolMapper) {
+        protocolMappers.add(protocolMapper);
     }
 
     public Set<ProtocolMapperModel> getGrantedProtocolMappers() {
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 63be7f0..e10cbed 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
@@ -226,6 +226,7 @@ public class ModelToRepresentation {
         ClientRepresentation rep = new ClientRepresentation();
         rep.setId(clientModel.getId());
         rep.setClientId(clientModel.getClientId());
+        rep.setName(clientModel.getName());
         rep.setEnabled(clientModel.isEnabled());
         rep.setAdminUrl(clientModel.getManagementUrl());
         rep.setPublicClient(clientModel.isPublicClient());
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 282d376..d5983cd 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
@@ -523,6 +523,7 @@ public class RepresentationToModel {
         logger.debug("Create client: {0}" + resourceRep.getClientId());
 
         ClientModel client = resourceRep.getId()!=null ? realm.addClient(resourceRep.getId(), resourceRep.getClientId()) : realm.addClient(resourceRep.getClientId());
+        if (resourceRep.getName() != null) client.setName(resourceRep.getName());
         if (resourceRep.isEnabled() != null) client.setEnabled(resourceRep.isEnabled());
         client.setManagementUrl(resourceRep.getAdminUrl());
         if (resourceRep.isSurrogateAuthRequired() != null)
@@ -614,6 +615,7 @@ public class RepresentationToModel {
 
     public static void updateClient(ClientRepresentation rep, ClientModel resource) {
         if (rep.getClientId() != null) resource.setClientId(rep.getClientId());
+        if (rep.getName() != null) resource.setName(rep.getName());
         if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
         if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
         if (rep.isConsentRequired() != null) resource.setConsentRequired(rep.isConsentRequired());
@@ -792,23 +794,25 @@ public class RepresentationToModel {
                     throw new RuntimeException("Unable to find client consent mappings for client: " + entry.getKey());
                 }
 
-                UserConsentModel consentModel = new UserConsentModel(newRealm, client.getId());
+                UserConsentModel consentModel = new UserConsentModel(client);
 
                 UserConsentRepresentation consentRep = entry.getValue();
                 if (consentRep.getGrantedRoles() != null) {
                     for (String roleId : consentRep.getGrantedRoles()) {
-                        if (newRealm.getRoleById(roleId) == null) {
+                        RoleModel role = newRealm.getRoleById(roleId);
+                        if (role == null) {
                             throw new RuntimeException("Unable to find realm role referenced in consent mappings of user " + user.getUsername() + ". Role ID: " + roleId);
                         }
-                        consentModel.addGrantedRole(roleId);
+                        consentModel.addGrantedRole(role);
                     }
                 }
                 if (consentRep.getGrantedProtocolMappers() != null) {
                     for (String mapperId : consentRep.getGrantedProtocolMappers()) {
-                        if (client.getProtocolMapperById(mapperId) == null) {
+                        ProtocolMapperModel protocolMapper = client.getProtocolMapperById(mapperId);
+                        if (protocolMapper == null) {
                             throw new RuntimeException("Unable to find protocol mapper referenced in consent mappings of user " + user.getUsername() + ". Protocol mapper ID: " + mapperId);
                         }
-                        consentModel.addGrantedProtocolMapper(mapperId);;
+                        consentModel.addGrantedProtocolMapper(protocolMapper);
                     }
                 }
                 user.addConsent(consentModel);
diff --git a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
index 7068a26..e7847e2 100755
--- a/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
+++ b/model/file/src/main/java/org/keycloak/models/file/adapter/ClientAdapter.java
@@ -69,6 +69,16 @@ public class ClientAdapter implements ClientModel {
     }
 
     @Override
+    public String getName() {
+        return entity.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+       entity.setName(name);
+    }
+
+    @Override
     public Set<String> getWebOrigins() {
         Set<String> result = new HashSet<String>();
         if (entity.getWebOrigins() != null) {
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 4dc4a03..48089bd 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
@@ -293,7 +293,7 @@ public class ClientAdapter implements ClientModel {
     @Override
     public String getClientId() {
         if (updated != null) return updated.getClientId();
-        return cached.getName();
+        return cached.getClientId();
     }
 
     @Override
@@ -304,6 +304,18 @@ public class ClientAdapter implements ClientModel {
     }
 
     @Override
+    public String getName() {
+        if (updated != null) return updated.getName();
+        return cached.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getDelegateForUpdate();
+        updated.setName(name);
+    }
+
+    @Override
     public boolean isSurrogateAuthRequired() {
         if (updated != null) return updated.isSurrogateAuthRequired();
         return cached.isSurrogateAuthRequired();
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 58d3cb0..8b8c045 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
@@ -21,6 +21,7 @@ import java.util.TreeMap;
  */
 public class CachedClient {
     private String id;
+    private String clientId;
     private String name;
     private String realm;
     private Set<String> redirectUris = new HashSet<String>();
@@ -49,7 +50,8 @@ public class CachedClient {
     public CachedClient(RealmCache cache, RealmProvider delegate, RealmModel realm, ClientModel model) {
         id = model.getId();
         secret = model.getSecret();
-        name = model.getClientId();
+        clientId = model.getClientId();
+        name = model.getName();
         this.realm = realm.getId();
         enabled = model.isEnabled();
         protocol = model.getProtocol();
@@ -85,6 +87,10 @@ public class CachedClient {
         return id;
     }
 
+    public String getClientId() {
+        return clientId;
+    }
+
     public String getName() {
         return name;
     }
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 b290e48..7e4906a 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
@@ -55,6 +55,16 @@ public class ClientAdapter implements ClientModel {
     }
 
     @Override
+    public String getName() {
+        return entity.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        entity.setName(name);
+    }
+
+    @Override
     public boolean isEnabled() {
         return entity.isEnabled();
     }
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 26322d4..ff6f14c 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
@@ -32,6 +32,8 @@ public class ClientEntity {
     @Id
     @Column(name="ID", length = 36)
     private String id;
+    @Column(name = "NAME")
+    private String name;
     @Column(name = "CLIENT_ID")
     private String clientId;
     @Column(name="ENABLED")
@@ -125,6 +127,14 @@ public class ClientEntity {
         this.id = id;
     }
 
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
     public boolean isEnabled() {
         return enabled;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
index 8cc29f7..5f92104 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
@@ -561,19 +561,27 @@ public class UserAdapter implements UserModel {
             return null;
         }
 
-        UserConsentModel model = new UserConsentModel(realm, entity.getClientId());
+        ClientModel client = realm.getClientById(entity.getClientId());
+        if (client == null) {
+            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+        }
+        UserConsentModel model = new UserConsentModel(client);
 
         Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
         if (grantedRoleEntities != null) {
             for (UserConsentRoleEntity grantedRole : grantedRoleEntities) {
-                model.addGrantedRole(grantedRole.getRoleId());
+                RoleModel grantedRoleModel = realm.getRoleById(grantedRole.getRoleId());
+                if (grantedRoleModel != null) {
+                    model.addGrantedRole(grantedRoleModel);
+                }
             }
         }
 
         Collection<UserConsentProtocolMapperEntity> grantedProtocolMapperEntities = entity.getGrantedProtocolMappers();
         if (grantedProtocolMapperEntities != null) {
             for (UserConsentProtocolMapperEntity grantedProtMapper : grantedProtocolMapperEntities) {
-                model.addGrantedProtocolMapper(grantedProtMapper.getProtocolMapperId());
+                ProtocolMapperModel protocolMapper = client.getProtocolMapperById(grantedProtMapper.getProtocolMapperId());
+                model.addGrantedProtocolMapper(protocolMapper );
             }
         }
 
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 9eae9f0..b0784f5 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
@@ -27,20 +27,20 @@ import java.util.Set;
  */
 public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> implements ClientModel {
 
-    protected final MongoClientEntity applicationEntity;
+    protected final MongoClientEntity clientEntity;
     private final RealmModel realm;
     protected  KeycloakSession session;
 
-    public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity applicationEntity, MongoStoreInvocationContext invContext) {
+    public ClientAdapter(KeycloakSession session, RealmModel realm, MongoClientEntity clientEntity, MongoStoreInvocationContext invContext) {
         super(invContext);
         this.session = session;
         this.realm = realm;
-        this.applicationEntity = applicationEntity;
+        this.clientEntity = clientEntity;
     }
 
     @Override
     public MongoClientEntity getMongoEntity() {
-        return applicationEntity;
+        return clientEntity;
     }
 
     @Override
@@ -60,6 +60,17 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
     }
 
     @Override
+    public String getName() {
+        return getMongoEntity().getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        getMongoEntity().setName(name);
+        updateMongoEntity();
+    }
+
+    @Override
     public void setClientId(String clientId) {
         getMongoEntity().setClientId(clientId);
         updateMongoEntity();
@@ -84,12 +95,12 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
 
     @Override
     public void addWebOrigin(String webOrigin) {
-        getMongoStore().pushItemToList(applicationEntity, "webOrigins", webOrigin, true, invocationContext);
+        getMongoStore().pushItemToList(clientEntity, "webOrigins", webOrigin, true, invocationContext);
     }
 
     @Override
     public void removeWebOrigin(String webOrigin) {
-        getMongoStore().pullItemFromList(applicationEntity, "webOrigins", webOrigin, invocationContext);
+        getMongoStore().pullItemFromList(clientEntity, "webOrigins", webOrigin, invocationContext);
     }
 
     @Override
@@ -111,12 +122,12 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
 
     @Override
     public void addRedirectUri(String redirectUri) {
-        getMongoStore().pushItemToList(applicationEntity, "redirectUris", redirectUri, true, invocationContext);
+        getMongoStore().pushItemToList(clientEntity, "redirectUris", redirectUri, true, invocationContext);
     }
 
     @Override
     public void removeRedirectUri(String redirectUri) {
-        getMongoStore().pullItemFromList(applicationEntity, "redirectUris", redirectUri, invocationContext);
+        getMongoStore().pullItemFromList(clientEntity, "redirectUris", redirectUri, invocationContext);
     }
 
     @Override
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
index b054793..1a4a9b5 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
@@ -462,12 +462,22 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
     }
 
     private UserConsentModel toConsentModel(UserConsentEntity entity) {
-        UserConsentModel model = new UserConsentModel(realm, entity.getClientId());
+        ClientModel client = realm.getClientById(entity.getClientId());
+        if (client == null) {
+            throw new ModelException("Client with id " + entity.getClientId() + " is not available");
+        }
+        UserConsentModel model = new UserConsentModel(client);
+
         for (String roleId : entity.getGrantedRoles()) {
-            model.addGrantedRole(roleId);
+            RoleModel roleModel = realm.getRoleById(roleId);
+            if (roleModel != null) {
+                model.addGrantedRole(roleModel);
+            }
         }
+
         for (String protMapperId : entity.getGrantedProtocolMappers()) {
-            model.addGrantedProtocolMapper(protMapperId);
+            ProtocolMapperModel protocolMapper = client.getProtocolMapperById(protMapperId);
+            model.addGrantedProtocolMapper(protocolMapper);
         }
         return model;
     }
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
index e380441..cc2c8cc 100644
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/ClientSessionAdapter.java
@@ -119,6 +119,17 @@ public class ClientSessionAdapter implements ClientSessionModel {
     }
 
     @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers();
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        entity.setProtocolMappers(protocolMappers);
+        update();
+    }
+
+    @Override
     public String getAuthMethod() {
         return entity.getAuthMethod();
     }
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
index 9c085fc..38d2ea5 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/entities/ClientSessionEntity.java
@@ -25,6 +25,7 @@ public class ClientSessionEntity extends SessionEntity {
     private ClientSessionModel.Action action;
 
     private Set<String> roles;
+    private Set<String> protocolMappers;
     private Map<String, String> notes;
 
     public String getClient() {
@@ -91,6 +92,14 @@ public class ClientSessionEntity extends SessionEntity {
         this.roles = roles;
     }
 
+    public Set<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
     public Map<String, String> getNotes() {
         return notes;
     }
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
index ebb47b6..74e795f 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/ClientSessionAdapter.java
@@ -7,6 +7,7 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.sessions.jpa.entities.ClientSessionEntity;
 import org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity;
+import org.keycloak.models.sessions.jpa.entities.ClientSessionProtocolMapperEntity;
 import org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity;
 import org.keycloak.models.sessions.jpa.entities.UserSessionEntity;
 
@@ -177,4 +178,36 @@ public class ClientSessionAdapter implements ClientSessionModel {
         }
         return roles;
     }
+
+    @Override
+    public Set<String> getProtocolMappers() {
+        Set<String> protMappers = new HashSet<String>();
+        if (entity.getProtocolMappers() != null) {
+            for (ClientSessionProtocolMapperEntity e : entity.getProtocolMappers()) {
+                protMappers.add(e.getProtocolMapperId());
+            }
+        }
+        return protMappers;
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        if (protocolMappers != null) {
+            for (String pm : protocolMappers) {
+                ClientSessionProtocolMapperEntity protMapperEntity = new ClientSessionProtocolMapperEntity();
+                protMapperEntity.setClientSession(entity);
+                protMapperEntity.setProtocolMapperId(pm);
+                em.persist(protMapperEntity);
+
+                entity.getProtocolMappers().add(protMapperEntity);
+            }
+        } else {
+            if (entity.getProtocolMappers() != null) {
+                for (ClientSessionProtocolMapperEntity pm : entity.getProtocolMappers()) {
+                    em.remove(pm);
+                }
+                entity.getProtocolMappers().clear();
+            }
+        }
+    }
 }
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
index c4bbe06..6f0c535 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionEntity.java
@@ -61,6 +61,9 @@ public class ClientSessionEntity {
     protected Collection<ClientSessionRoleEntity> roles = new ArrayList<ClientSessionRoleEntity>();
 
     @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
+    protected Collection<ClientSessionProtocolMapperEntity> protocolMappers = new ArrayList<ClientSessionProtocolMapperEntity>();
+
+    @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true, mappedBy="clientSession")
     protected Collection<ClientSessionNoteEntity> notes = new ArrayList<ClientSessionNoteEntity>();
 
     public String getId() {
@@ -127,6 +130,14 @@ public class ClientSessionEntity {
         this.roles = roles;
     }
 
+    public Collection<ClientSessionProtocolMapperEntity> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Collection<ClientSessionProtocolMapperEntity> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
     public Collection<ClientSessionNoteEntity> getNotes() {
         return notes;
     }
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java
new file mode 100644
index 0000000..628e0f3
--- /dev/null
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/entities/ClientSessionProtocolMapperEntity.java
@@ -0,0 +1,98 @@
+package org.keycloak.models.sessions.jpa.entities;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+@NamedQueries({
+        @NamedQuery(name = "removeClientSessionProtMapperByUser", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and s.userId = :userId))"),
+        @NamedQuery(name = "removeClientSessionProtMapperByClient", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.clientId = :clientId and c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionProtMapperByRealm", query="delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.realmId = :realmId)"),
+        @NamedQuery(name = "removeClientSessionProtMapperByExpired", query = "delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IN (select s from UserSessionEntity s where s.realmId = :realmId and (s.started < :maxTime or s.lastSessionRefresh < :idleTime)))"),
+        @NamedQuery(name = "removeDetachedClientSessionProtMapperByExpired", query = "delete from ClientSessionProtocolMapperEntity pm where pm.clientSession IN (select c from ClientSessionEntity c where c.session IS NULL and c.realmId = :realmId and c.timestamp < :maxTime )")
+})
+@Table(name="CLIENT_SESSION_PROT_MAPPER")
+@Entity
+@IdClass(ClientSessionProtocolMapperEntity.Key.class)
+public class ClientSessionProtocolMapperEntity {
+
+    @Id
+    @ManyToOne(fetch= FetchType.LAZY)
+    @JoinColumn(name="CLIENT_SESSION")
+    protected ClientSessionEntity clientSession;
+
+    @Id
+    @Column(name="PROTOCOL_MAPPER_ID")
+    protected String protocolMapperId;
+
+    public ClientSessionEntity getClientSession() {
+        return clientSession;
+    }
+
+    public void setClientSession(ClientSessionEntity clientSession) {
+        this.clientSession = clientSession;
+    }
+
+    public String getProtocolMapperId() {
+        return protocolMapperId;
+    }
+
+    public void setProtocolMapperId(String protocolMapperId) {
+        this.protocolMapperId = protocolMapperId;
+    }
+
+    public static class Key implements Serializable {
+
+        protected ClientSessionEntity clientSession;
+
+        protected String protocolMapperId;
+
+        public Key() {
+        }
+
+        public Key(ClientSessionEntity clientSession, String protocolMapperId) {
+            this.clientSession = clientSession;
+            this.protocolMapperId = protocolMapperId;
+        }
+
+        public ClientSessionEntity getClientSession() {
+            return clientSession;
+        }
+
+        public String getProtocolMapperId() {
+            return protocolMapperId;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            Key key = (Key) o;
+
+            if (!protocolMapperId.equals(key.protocolMapperId)) return false;
+            if (!clientSession.getId().equals(key.clientSession.getId())) return false;
+
+            return true;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = clientSession.getId().hashCode();
+            result = 31 * result + protocolMapperId.hashCode();
+            return result;
+        }
+    }
+}
diff --git a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
index 0731de3..23086d9 100755
--- a/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
+++ b/model/sessions-jpa/src/main/java/org/keycloak/models/sessions/jpa/JpaUserSessionProvider.java
@@ -214,6 +214,10 @@ public class JpaUserSessionProvider implements UserSessionProvider {
                 .setParameter("realmId", realm.getId())
                 .setParameter("userId", user.getId())
                 .executeUpdate();
+        em.createNamedQuery("removeClientSessionProtMapperByUser")
+                .setParameter("realmId", realm.getId())
+                .setParameter("userId", user.getId())
+                .executeUpdate();
         em.createNamedQuery("removeClientSessionByUser")
                 .setParameter("realmId", realm.getId())
                 .setParameter("userId", user.getId())
@@ -238,6 +242,10 @@ public class JpaUserSessionProvider implements UserSessionProvider {
                 .setParameter("realmId", realm.getId())
                 .setParameter("maxTime", dettachedClientSessionExpired)
                 .executeUpdate();
+        em.createNamedQuery("removeDetachedClientSessionProtMapperByExpired")
+                .setParameter("realmId", realm.getId())
+                .setParameter("maxTime", dettachedClientSessionExpired)
+                .executeUpdate();
         em.createNamedQuery("removeDetachedClientSessionNoteByExpired")
                 .setParameter("realmId", realm.getId())
                 .setParameter("maxTime", dettachedClientSessionExpired)
@@ -251,6 +259,11 @@ public class JpaUserSessionProvider implements UserSessionProvider {
                 .setParameter("maxTime", maxTime)
                 .setParameter("idleTime", idleTime)
                 .executeUpdate();
+        em.createNamedQuery("removeClientSessionProtMapperByExpired")
+                .setParameter("realmId", realm.getId())
+                .setParameter("maxTime", maxTime)
+                .setParameter("idleTime", idleTime)
+                .executeUpdate();
         em.createNamedQuery("removeClientSessionNoteByExpired")
                 .setParameter("realmId", realm.getId())
                 .setParameter("maxTime", maxTime)
@@ -277,6 +290,7 @@ public class JpaUserSessionProvider implements UserSessionProvider {
     public void removeUserSessions(RealmModel realm) {
         em.createNamedQuery("removeClientSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate();
         em.createNamedQuery("removeClientSessionRoleByRealm").setParameter("realmId", realm.getId()).executeUpdate();
+        em.createNamedQuery("removeClientSessionProtMapperByRealm").setParameter("realmId", realm.getId()).executeUpdate();
         em.createNamedQuery("removeClientSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
         em.createNamedQuery("removeUserSessionNoteByRealm").setParameter("realmId", realm.getId()).executeUpdate();
         em.createNamedQuery("removeUserSessionByRealm").setParameter("realmId", realm.getId()).executeUpdate();
@@ -292,6 +306,7 @@ public class JpaUserSessionProvider implements UserSessionProvider {
     public void onClientRemoved(RealmModel realm, ClientModel client) {
         em.createNamedQuery("removeClientSessionNoteByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
         em.createNamedQuery("removeClientSessionRoleByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
+        em.createNamedQuery("removeClientSessionProtMapperByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
         em.createNamedQuery("removeClientSessionByClient").setParameter("realmId", realm.getId()).setParameter("clientId", client.getId()).executeUpdate();
     }
 
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
index 62a3246..daa6e3f 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/ClientSessionAdapter.java
@@ -106,6 +106,16 @@ public class ClientSessionAdapter implements ClientSessionModel {
     }
 
     @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers();
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        entity.setProtocolMappers(protocolMappers);
+    }
+
+    @Override
     public String getNote(String name) {
         return entity.getNotes().get(name);
     }
diff --git a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
index dd945de..ca30496 100755
--- a/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
+++ b/model/sessions-mem/src/main/java/org/keycloak/models/sessions/mem/entities/ClientSessionEntity.java
@@ -23,6 +23,7 @@ public class ClientSessionEntity {
     private int timestamp;
     private ClientSessionModel.Action action;
     private Set<String> roles;
+    private Set<String> protocolMappers;
     private Map<String, String> notes = new HashMap<String, String>();
 
     public String getId() {
@@ -89,6 +90,14 @@ public class ClientSessionEntity {
         this.roles = roles;
     }
 
+    public Set<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
     public Map<String, String> getNotes() {
         return notes;
     }
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
index 12efd4a..649ffcf 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/ClientSessionAdapter.java
@@ -121,6 +121,23 @@ public class ClientSessionAdapter extends AbstractMongoAdapter<MongoClientSessio
     }
 
     @Override
+    public Set<String> getProtocolMappers() {
+        return entity.getProtocolMappers() != null ? new HashSet<String>(entity.getProtocolMappers()) : null;
+    }
+
+    @Override
+    public void setProtocolMappers(Set<String> protocolMappers) {
+        if (protocolMappers == null) {
+            entity.setProtocolMappers(null);
+        } else {
+            List<String> list = new LinkedList<String>();
+            list.addAll(protocolMappers);
+            entity.setProtocolMappers(list);
+        }
+        updateMongoEntity();
+    }
+
+    @Override
     public String getNote(String name) {
         return entity.getNotes().get(name);
     }
diff --git a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
index 91ec682..b5abede 100755
--- a/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
+++ b/model/sessions-mongo/src/main/java/org/keycloak/models/sessions/mongo/entities/MongoClientSessionEntity.java
@@ -27,6 +27,7 @@ public class MongoClientSessionEntity extends AbstractIdentifiableEntity impleme
     private int timestamp;
     private ClientSessionModel.Action action;
     private List<String> roles;
+    private List<String> protocolMappers;
     private Map<String, String> notes = new HashMap<String, String>();
 
     public String getId() {
@@ -93,6 +94,14 @@ public class MongoClientSessionEntity extends AbstractIdentifiableEntity impleme
         this.roles = roles;
     }
 
+    public List<String> getProtocolMappers() {
+        return protocolMappers;
+    }
+
+    public void setProtocolMappers(List<String> protocolMappers) {
+        this.protocolMappers = protocolMappers;
+    }
+
     public Map<String, String> getNotes() {
         return notes;
     }
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
index 677b2bf..f4d5bd4 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
@@ -11,12 +11,14 @@ import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.protocol.saml.SamlProtocol;
 import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
 import org.keycloak.dom.saml.v2.assertion.AttributeType;
+import org.keycloak.services.managers.ClientSessionCode;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -96,8 +98,8 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
         List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
         KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
         AttributeType singleAttributeType = null;
-        for (ProtocolMapperModel mapping : clientSession.getClient().getProtocolMappers()) {
-            if (!mapping.getProtocol().equals(SamlProtocol.LOGIN_PROTOCOL)) continue;
+        Set<ProtocolMapperModel> requestedProtocolMappers = new ClientSessionCode(clientSession.getRealm(), clientSession).getRequestedProtocolMappers();
+        for (ProtocolMapperModel mapping : requestedProtocolMappers) {
 
             ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
             if (mapper == null) continue;
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
index 747c43c..315e685 100755
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java
@@ -282,9 +282,8 @@ public class SamlProtocol implements LoginProtocol {
         List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
         ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null;
 
-        Set<ProtocolMapperModel> mappings = client.getProtocolMappers();
+        Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers();
         for (ProtocolMapperModel mapping : mappings) {
-            if (!mapping.getProtocol().equals(SamlProtocol.LOGIN_PROTOCOL)) continue;
 
             ProtocolMapper mapper = (ProtocolMapper)session.getKeycloakSessionFactory().getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
             if (mapper == null) continue;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index f337163..7900d90 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -27,6 +27,7 @@ import org.keycloak.events.Details;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
@@ -122,10 +123,11 @@ public class UserInfoEndpoint {
         }
 
         UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
+        ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession());
         ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
         UserModel userModel = userSession.getUser();
         AccessToken userInfo = new AccessToken();
-        tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, null);
+        tokenManager.transformAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
 
         event
             .detail(Details.USERNAME, userModel.getUsername())
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 8d9ab8c..f77fbdd 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -27,6 +27,7 @@ import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.representations.IDToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.ClientSessionCode;
 import org.keycloak.util.Time;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -208,6 +209,14 @@ public class TokenManager {
             requestedRoles.add(r.getId());
         }
         clientSession.setRoles(requestedRoles);
+
+        Set<String> requestedProtocolMappers = new HashSet<String>();
+        for (ProtocolMapperModel protocolMapper : clientSession.getClient().getProtocolMappers()) {
+            if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
+                requestedProtocolMappers.add(protocolMapper.getId());
+            }
+        }
+        clientSession.setProtocolMappers(requestedProtocolMappers);
     }
 
     public static void dettachClientSession(UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) {
@@ -218,6 +227,7 @@ public class TokenManager {
 
         clientSession.setUserSession(null);
         clientSession.setRoles(null);
+        clientSession.setProtocolMappers(null);
 
         if (userSession.getClientSessions().isEmpty()) {
             sessions.removeUserSession(realm, userSession);
@@ -274,23 +284,20 @@ public class TokenManager {
 
     public AccessToken transformAccessToken(KeycloakSession session, AccessToken token, RealmModel realm, ClientModel client, UserModel user,
                                             UserSessionModel userSession, ClientSessionModel clientSession) {
-        Set<ProtocolMapperModel> mappings = client.getProtocolMappers();
+        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
         KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
         for (ProtocolMapperModel mapping : mappings) {
-            if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue;
 
             ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
             if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue;
             token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
 
-
-
         }
         return token;
     }
     public void transformIDToken(KeycloakSession session, IDToken token, RealmModel realm, ClientModel client, UserModel user,
                                       UserSessionModel userSession, ClientSessionModel clientSession) {
-        Set<ProtocolMapperModel> mappings = client.getProtocolMappers();
+        Set<ProtocolMapperModel> mappings = new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
         KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
         for (ProtocolMapperModel mapping : mappings) {
             if (!mapping.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) continue;
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 7647b36..8e363bb 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -439,8 +439,8 @@ public class AuthenticationManager {
             }
 
             List<ProtocolMapperModel> protocolMappers = new LinkedList<ProtocolMapperModel>();
-            for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) {
-                if (protocolMapper.isConsentRequired() && protocolMapper.getProtocol().equals(clientSession.getAuthMethod()) && protocolMapper.getConsentText() != null) {
+            for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) {
+                if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) {
                     if (grantedConsent == null || !grantedConsent.isProtocolMapperGranted(protocolMapper)) {
                         protocolMappers.add(protocolMapper);
                     }
diff --git a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
index 9e52c97..99fc5f2 100755
--- a/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientSessionCode.java
@@ -2,6 +2,7 @@ package org.keycloak.services.managers;
 
 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.RequiredAction;
@@ -112,12 +113,25 @@ public class ClientSessionCode {
         for (String roleId : clientSession.getRoles()) {
             RoleModel role = realm.getRoleById(roleId);
             if (role != null) {
-                requestedRoles.add(realm.getRoleById(roleId));
+                requestedRoles.add(role);
             }
         }
         return requestedRoles;
     }
 
+    public Set<ProtocolMapperModel> getRequestedProtocolMappers() {
+        Set<ProtocolMapperModel> requestedProtocolMappers = new HashSet<ProtocolMapperModel>();
+        if (clientSession.getProtocolMappers() != null) {
+            for (String protocolMapperId : clientSession.getProtocolMappers()) {
+                ProtocolMapperModel protocolMapper = clientSession.getClient().getProtocolMapperById(protocolMapperId);
+                if (protocolMapper != null) {
+                    requestedProtocolMappers.add(protocolMapper);
+                }
+            }
+        }
+        return requestedProtocolMappers;
+    }
+
     public void setAction(ClientSessionModel.Action action) {
         clientSession.setAction(action);
         clientSession.setNote(ACTION_KEY, UUID.randomUUID().toString());
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 8493397..3d56a2a 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -94,6 +94,7 @@ public class RealmManager {
     protected void setupAdminConsole(RealmModel realm) {
         ClientModel adminConsole = realm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
         if (adminConsole == null) adminConsole = new ClientManager(this).createClient(realm, Constants.ADMIN_CONSOLE_CLIENT_ID);
+        adminConsole.setName("${client_" + Constants.ADMIN_CONSOLE_CLIENT_ID + "}");
         String baseUrl = contextPath + "/admin/" + realm.getName() + "/console";
         adminConsole.setBaseUrl(baseUrl + "/index.html");
         adminConsole.setEnabled(true);
@@ -184,6 +185,7 @@ public class RealmManager {
         ClientModel realmAdminClient = realm.getClientByClientId(realmAdminClientId);
         if (realmAdminClient == null) {
             realmAdminClient = clientManager.createClient(realm, realmAdminClientId);
+            realmAdminClient.setName("${client_" + realmAdminClientId + "}");
         }
         RoleModel adminRole = realmAdminClient.addRole(AdminRoles.REALM_ADMIN);
         adminRole.setDescription("${role_" + AdminRoles.REALM_ADMIN + "}");
@@ -202,6 +204,7 @@ public class RealmManager {
         ClientModel client = realm.getClientNameMap().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
         if (client == null) {
             client = new ClientManager(this).createClient(realm, Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
+            client.setName("${client_" + Constants.ACCOUNT_MANAGEMENT_CLIENT_ID + "}");
             client.setEnabled(true);
             client.setFullScopeAllowed(false);
             String base = contextPath + "/realms/" + realm.getName() + "/account";
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 3a775e1..9b1edae 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -349,10 +349,10 @@ public class AccountService {
         return forwardToPage("sessions", AccountPages.SESSIONS);
     }
 
-    @Path("access")
+    @Path("applications")
     @GET
-    public Response accessPage() {
-        return forwardToPage("access", AccountPages.ACCESS);
+    public Response applicationsPage() {
+        return forwardToPage("applications", AccountPages.APPLICATIONS);
     }
 
     /**
@@ -494,7 +494,7 @@ public class AccountService {
     @POST
     public Response processRevokeGrant(final MultivaluedMap<String, String> formData) {
         if (auth == null) {
-            return login("access");
+            return login("applications");
         }
 
         require(AccountRoles.MANAGE_ACCOUNT);
@@ -502,11 +502,11 @@ public class AccountService {
 
         String clientId = formData.getFirst("clientId");
         if (clientId == null) {
-            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.ACCESS);
+            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
         }
         ClientModel client = realm.getClientById(clientId);
         if (client == null) {
-            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.ACCESS);
+            return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS);
         }
 
         // Revoke grant in UserModel
@@ -527,7 +527,7 @@ public class AccountService {
         event.event(EventType.REVOKE_GRANT).client(auth.getClient()).user(auth.getUser()).detail(Details.REVOKED_CLIENT, client.getClientId()).success();
         setReferrerOnPage();
 
-        return account.setSuccess(Messages.SUCCESS_GRANT_REVOKED).createResponse(AccountPages.ACCESS);
+        return account.setSuccess(Messages.SUCCESS_GRANT_REVOKED).createResponse(AccountPages.APPLICATIONS);
     }
 
     /**
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 d4aa8d7..aeb3e2a 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -34,6 +34,7 @@ import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.login.LoginFormsProvider;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserConsentModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelException;
@@ -611,16 +612,15 @@ public class LoginActionsService {
 
         UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
         if (grantedConsent == null) {
-            grantedConsent = new UserConsentModel(realm, client.getId());
+            grantedConsent = new UserConsentModel(client);
             user.addConsent(grantedConsent);
         }
-        for (String roleId : clientSession.getRoles()) {
-            grantedConsent.addGrantedRole(roleId);
+        for (RoleModel role : accessCode.getRequestedRoles()) {
+            grantedConsent.addGrantedRole(role);
         }
-        // TODO: It's not 100% sure that approved protocolMappers are same like the protocolMappers retrieved here from the client. Maybe clientSession.setProtocolMappers/getProtocolMappers should be added...
-        for (ProtocolMapperModel protocolMapper : client.getProtocolMappers()) {
-            if (protocolMapper.isConsentRequired() && protocolMapper.getProtocol().equals(clientSession.getAuthMethod()) && protocolMapper.getConsentText() != null) {
-                grantedConsent.addGrantedProtocolMapper(protocolMapper.getId());
+        for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) {
+            if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) {
+                grantedConsent.addGrantedProtocolMapper(protocolMapper);
             }
         }
         user.updateConsent(grantedConsent);
diff --git a/services/src/main/java/org/keycloak/services/Urls.java b/services/src/main/java/org/keycloak/services/Urls.java
index 0d3cc32..93b479b 100755
--- a/services/src/main/java/org/keycloak/services/Urls.java
+++ b/services/src/main/java/org/keycloak/services/Urls.java
@@ -39,8 +39,8 @@ import java.net.URI;
  */
 public class Urls {
 
-    public static URI accountAccessPage(URI baseUri, String realmId) {
-        return accountBase(baseUri).path(AccountService.class, "accessPage").build(realmId);
+    public static URI accountApplicationsPage(URI baseUri, String realmId) {
+        return accountBase(baseUri).path(AccountService.class, "applicationsPage").build(realmId);
     }
 
     public static UriBuilder accountBase(URI baseUri) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index 73f7655..526813b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -21,7 +21,7 @@ import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.testsuite.Constants;
 import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.pages.AccountAccessPage;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
 import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.pages.OAuthGrantPage;
@@ -89,7 +89,7 @@ public class ProfileTest {
     protected AccountUpdateProfilePage profilePage;
 
     @WebResource
-    protected AccountAccessPage accountAccessPage;
+    protected AccountApplicationsPage accountApplicationsPage;
 
     @WebResource
     protected LoginPage loginPage;
@@ -191,8 +191,8 @@ public class ProfileTest {
 
         assertEquals("test-user@localhost", profile.getString("username"));
 
-        accountAccessPage.open();
-        accountAccessPage.revokeGrant("third-party");
+        accountApplicationsPage.open();
+        accountApplicationsPage.revokeGrant("third-party");
     }
 
     @Test
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 0312446..afee212 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
@@ -167,6 +167,7 @@ public class AdminAPITest {
 
     protected void checkAppUpdate(ClientRepresentation appRep, ClientRepresentation storedApp) {
         if (appRep.getClientId() != null) Assert.assertEquals(appRep.getClientId(), storedApp.getClientId());
+        if (appRep.getName() != null) Assert.assertEquals(appRep.getName(), storedApp.getName());
         if (appRep.isEnabled() != null) Assert.assertEquals(appRep.isEnabled(), storedApp.isEnabled());
         if (appRep.isBearerOnly() != null) Assert.assertEquals(appRep.isBearerOnly(), storedApp.isBearerOnly());
         if (appRep.isPublicClient() != null) Assert.assertEquals(appRep.isPublicClient(), storedApp.isPublicClient());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
index e1f4c83..686355c 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java
@@ -8,7 +8,7 @@ import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.services.Urls;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.testsuite.Constants;
-import org.keycloak.testsuite.pages.AccountAccessPage;
+import org.keycloak.testsuite.pages.AccountApplicationsPage;
 import org.keycloak.testsuite.pages.OAuthGrantPage;
 import org.keycloak.testsuite.rule.AbstractKeycloakRule;
 import org.keycloak.testsuite.rule.WebResource;
@@ -53,17 +53,17 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractIdentityProviderT
     private OAuthGrantPage grantPage;
 
     @WebResource
-    protected AccountAccessPage accountAccessPage;
+    protected AccountApplicationsPage accountApplicationsPage;
 
     @Override
     protected void revokeGrant() {
         String currentUrl = driver.getCurrentUrl();
 
-        String accountAccessPath = Urls.accountAccessPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString();
-        accountAccessPage.setPath(accountAccessPath);
-        accountAccessPage.open();
+        String accountAccessPath = Urls.accountApplicationsPage(UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT).port(PORT).build(), "realm-with-oidc-identity-provider").toString();
+        accountApplicationsPage.setPath(accountAccessPath);
+        accountApplicationsPage.open();
         try {
-            accountAccessPage.revokeGrant("broker-app");
+            accountApplicationsPage.revokeGrant("broker-app");
         } catch (NoSuchElementException e) {
             System.err.println("Couldn't revoke broker-app application, maybe because it wasn't granted or user not logged");
         }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
index e56d462..efbefa6 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ClientModelTest.java
@@ -31,6 +31,7 @@ public class ClientModelTest extends AbstractModelTest {
 
         realm = realmManager.createRealm("original");
         client = realm.addClient("application");
+        client.setName("Application");
         client.setBaseUrl("http://base");
         client.setManagementUrl("http://management");
         client.setClientId("app-name");
@@ -85,6 +86,7 @@ public class ClientModelTest extends AbstractModelTest {
 
     public static void assertEquals(ClientModel expected, ClientModel actual) {
         Assert.assertEquals(expected.getClientId(), actual.getClientId());
+        Assert.assertEquals(expected.getName(), actual.getName());
         Assert.assertEquals(expected.getBaseUrl(), actual.getBaseUrl());
         Assert.assertEquals(expected.getManagementUrl(), actual.getManagementUrl());
         Assert.assertEquals(expected.getDefaultRoles(), actual.getDefaultRoles());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
index bea52c4..317c101 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/ImportTest.java
@@ -99,6 +99,7 @@ public class ImportTest extends AbstractModelTest {
         Assert.assertTrue(clients.values().contains(accountApp));
         realm.getClients().containsAll(clients.values());
 
+        Assert.assertEquals("Applicationn", application.getName());
         Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
         Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
         Assert.assertEquals(2, appRegisteredNodes.size());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
index 97cb24b..92ef5dd 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserConsentModelTest.java
@@ -46,15 +46,15 @@ public class UserConsentModelTest extends AbstractModelTest {
         UserModel john = session.users().addUser(realm, "john");
         UserModel mary = session.users().addUser(realm, "mary");
 
-        UserConsentModel johnFooGrant = new UserConsentModel(realm, fooClient.getId());
-        johnFooGrant.addGrantedRole(realmRole.getId());
-        johnFooGrant.addGrantedRole(barClientRole.getId());
-        johnFooGrant.addGrantedProtocolMapper(fooMapper.getId());
+        UserConsentModel johnFooGrant = new UserConsentModel(fooClient);
+        johnFooGrant.addGrantedRole(realmRole);
+        johnFooGrant.addGrantedRole(barClientRole);
+        johnFooGrant.addGrantedProtocolMapper(fooMapper);
         john.addConsent(johnFooGrant);
 
-        UserConsentModel johnBarGrant = new UserConsentModel(realm, barClient.getId());
-        johnBarGrant.addGrantedProtocolMapper(barMapper.getId());
-        johnBarGrant.addGrantedRole(realmRole.getId());
+        UserConsentModel johnBarGrant = new UserConsentModel(barClient);
+        johnBarGrant.addGrantedProtocolMapper(barMapper);
+        johnBarGrant.addGrantedRole(realmRole);
 
         // Update should fail as grant doesn't yet exists
         try {
@@ -65,9 +65,9 @@ public class UserConsentModelTest extends AbstractModelTest {
 
         john.addConsent(johnBarGrant);
 
-        UserConsentModel maryFooGrant = new UserConsentModel(realm, fooClient.getId());
-        maryFooGrant.addGrantedRole(realmRole.getId());
-        maryFooGrant.addGrantedProtocolMapper(fooMapper.getId());
+        UserConsentModel maryFooGrant = new UserConsentModel(fooClient);
+        maryFooGrant.addGrantedRole(realmRole);
+        maryFooGrant.addGrantedProtocolMapper(fooMapper);
         mary.addConsent(maryFooGrant);
 
         commit();
@@ -143,7 +143,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         johnConsent.getGrantedRoles().remove(realmRole);
 
         RoleModel newRealmRole = realm.addRole("new-realm-role");
-        johnConsent.addGrantedRole(newRealmRole.getId());
+        johnConsent.addGrantedRole(newRealmRole);
 
         john.updateConsent(johnConsent);
 
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 b706203..c5b236a 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
@@ -101,6 +101,9 @@ public class UserSessionProviderTest {
         assertEquals(2, session1.getRoles().size());
         assertTrue(session1.getRoles().contains("one"));
         assertTrue(session1.getRoles().contains("two"));
+        assertEquals(2, session1.getProtocolMappers().size());
+        assertTrue(session1.getProtocolMappers().contains("mapper-one"));
+        assertTrue(session1.getProtocolMappers().contains("mapper-two"));
     }
 
     @Test
@@ -470,12 +473,13 @@ public class UserSessionProviderTest {
         assertNotNull(session.sessions().getUserLoginFailure(realm, "user2"));
     }
 
-    private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles) {
+    private ClientSessionModel createClientSession(ClientModel client, UserSessionModel userSession, String redirect, String state, Set<String> roles, Set<String> protocolMappers) {
         ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
         if (userSession != null) clientSession.setUserSession(userSession);
         clientSession.setRedirectUri(redirect);
         if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
         if (roles != null) clientSession.setRoles(roles);
+        if (protocolMappers != null) clientSession.setProtocolMappers(protocolMappers);
         return clientSession;
     }
 
@@ -487,14 +491,18 @@ public class UserSessionProviderTest {
         roles.add("one");
         roles.add("two");
 
-        createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles);
-        createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>());
+        Set<String> protocolMappers = new HashSet<String>();
+        protocolMappers.add("mapper-one");
+        protocolMappers.add("mapper-two");
+
+        createClientSession(realm.getClientByClientId("test-app"), sessions[0], "http://redirect", "state", roles, protocolMappers);
+        createClientSession(realm.getClientByClientId("third-party"), sessions[0], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
 
         sessions[1] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user1", realm), "user1", "127.0.0.2", "form", true, null, null);
-        createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet<String>());
+        createClientSession(realm.getClientByClientId("test-app"), sessions[1], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
 
         sessions[2] = session.sessions().createUserSession(realm, session.users().getUserByUsername("user2", realm), "user2", "127.0.0.3", "form", true, null, null);
-        createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet<String>());
+        createClientSession(realm.getClientByClientId("test-app"), sessions[2], "http://redirect", "state", new HashSet<String>(), new HashSet<String>());
 
         resetSession();
 
diff --git a/testsuite/integration/src/test/resources/model/testrealm.json b/testsuite/integration/src/test/resources/model/testrealm.json
index 1c0b7e6..e6d4d18 100755
--- a/testsuite/integration/src/test/resources/model/testrealm.json
+++ b/testsuite/integration/src/test/resources/model/testrealm.json
@@ -107,9 +107,10 @@
             ]
         }
     ],
-    "applications": [
+    "clients": [
         {
-            "name": "Application",
+            "clientId": "Application",
+            "name": "Applicationn",
             "enabled": true,
             "nodeReRegistrationTimeout": 50,
             "registeredNodes": {
@@ -118,7 +119,8 @@
             }
         },
         {
-            "name": "OtherApp",
+            "clientId": "OtherApp",
+            "name": "Other Application",
             "enabled": true,
             "protocolMappers" : [
                 {