keycloak-uncached
Changes
adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakAdapterConfigService.java 7(+6 -1)
adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakAdapterConfigService.java 7(+6 -1)
adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java 7(+6 -1)
adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java 14(+0 -14)
adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/RealmAddHandler.java 4(+0 -4)
adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java 19(+0 -19)
adapters/oidc/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/extension/RealmDefinitionTestCase.java 86(+0 -86)
adapters/saml/undertow/pom.xml 6(+0 -6)
dependencies/server-all/pom.xml 78(+11 -67)
distribution/demo-dist/pom.xml 44(+19 -25)
distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml 5(+0 -5)
distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-themes/main/module.xml 36(+0 -36)
distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-extensions/main/module.xml 1(+0 -1)
distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/sonatype/sisu/main/module.xml 1(+0 -1)
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/AbstractLDAPFederationMapperFactory.java 6(+4 -2)
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java 6(+6 -0)
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java 3(+2 -1)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java 12(+12 -0)
model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java 50(+47 -3)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java 8(+8 -0)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java 18(+18 -0)
pom.xml 1(+1 -0)
server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java 3(+2 -1)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java 4(+1 -3)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java 5(+3 -2)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java 9(+5 -4)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java 3(+2 -1)
services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java 3(+2 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java 5(+3 -2)
services/src/main/java/org/keycloak/authentication/authenticators/browser/ConditionalOtpFormAuthenticatorFactory.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticatorFactory.java 9(+8 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java 3(+2 -1)
services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java 2(+1 -1)
services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java 3(+0 -3)
services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java 4(+1 -3)
services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java 3(+1 -2)
services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java 3(+2 -1)
services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java 5(+3 -2)
services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java 4(+1 -3)
services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java 4(+2 -2)
services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java 47(+47 -0)
services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java 28(+1 -27)
services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java 87(+57 -30)
services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java 21(+19 -2)
services/src/main/java/org/keycloak/protocol/oidc/mappers/UserRealmRoleMappingMapper.java 22(+20 -2)
services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java 15(+4 -11)
services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientTemplatesClientRegistrationPolicyFactory.java 2(+1 -1)
services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ProtocolMappersClientRegistrationPolicyFactory.java 2(+1 -1)
services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java 16(+9 -7)
services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java 4(+2 -2)
services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java 7(+4 -3)
services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java 5(+3 -2)
services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java 4(+2 -2)
services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java 3(+3 -0)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractKeycloakIdentityProviderTest.java 2(+1 -1)
testsuite/integration/src/test/java/org/keycloak/testsuite/broker/OIDCKeyCloakServerBrokerBasicTest.java 2(+1 -1)
testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-kc-oidc.json 21(+10 -11)
testsuite/integration-arquillian/pom.xml 19(+19 -0)
testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java 12(+6 -6)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java 5(+3 -2)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java 24(+18 -6)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java 21(+13 -8)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java 3(+2 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java 8(+8 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java 11(+11 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java 42(+42 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java 12(+0 -12)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java 171(+146 -25)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/ClientRegistrationPoliciesTest.java 4(+2 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCPairwiseClientRegistrationTest.java 15(+15 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java 90(+49 -41)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java 132(+0 -132)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java 244(+244 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/GroupBuilder.java 85(+85 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java 20(+20 -0)
testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCFilterAdapterTest.java 12(+12 -0)
themes/src/main/resources/theme/keycloak/common/resources/lib/angular/angular-mocks.js 2433(+0 -2433)
themes/src/main/resources/theme/keycloak/common/resources/lib/angular/angular-scenario.js 40024(+0 -40024)
themes/src/main/resources/theme/keycloak/common/resources/lib/angular/angular-translate-storage-cookie.js 71(+0 -71)
themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter.js 185(+0 -185)
themes/src/main/resources/theme/keycloak/common/resources/lib/angular/jstd-scenario-adapter-config.js 6(+0 -6)
themes/src/main/resources/theme/keycloak/common/resources/lib/components/font-awesome/fonts/FontAwesome.otf 0(+0 -0)
themes/src/main/resources/theme/keycloak/common/resources/lib/fileupload/angular-file-upload.js 156(+0 -156)
themes/src/main/resources/theme/keycloak/common/resources/lib/fileupload/angular-file-upload-html5-shim.js 25(+0 -25)
themes/src/main/resources/theme/keycloak/common/resources/lib/fileupload/angular-file-upload-shim.js 215(+0 -215)
themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/css/patternfly.min.css 10(+0 -10)
themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/js/patternfly.js 212(+0 -212)
themes/src/main/resources/theme/keycloak/common/resources/lib/patternfly/js/patternfly.min.js 1(+0 -1)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2.jquery.json 36(+0 -36)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2.js 3137(+0 -3137)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ar.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ca.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_cs.js 49(+0 -49)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_da.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_de.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_el.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_en.js.template 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_es.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_et.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_eu.js 43(+0 -43)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_fi.js 28(+0 -28)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_fr.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_gl.js 43(+0 -43)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_he.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_hr.js 42(+0 -42)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_hu.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_id.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_is.js 16(+0 -16)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_it.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ja.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ko.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_lt.js 29(+0 -29)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_lv.js 16(+0 -16)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_mk.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_nl.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_no.js 18(+0 -18)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_pl.js 37(+0 -37)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_pt-BR.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_pt-PT.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ro.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ru.js 15(+0 -15)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_sk.js 48(+0 -48)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_sv.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_tr.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_ua.js 17(+0 -17)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_vi.js 18(+0 -18)
themes/src/main/resources/theme/keycloak/common/resources/lib/select2-3.4.1/select2_locale_zh-CN.js 14(+0 -14)
Details
diff --git a/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakAdapterConfigService.java b/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakAdapterConfigService.java
index 210473c..b0bd654 100755
--- a/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakAdapterConfigService.java
+++ b/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakAdapterConfigService.java
@@ -165,6 +165,9 @@ public final class KeycloakAdapterConfigService {
 
     protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
         ModelNode deployment = getSecureDeployment(deploymentUnit);
+        if (! deployment.isDefined()) {
+            return false;
+        }
         ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
         return resource.isDefined();
     }
@@ -202,7 +205,9 @@ public final class KeycloakAdapterConfigService {
 
     private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
         String deploymentName = preferredDeploymentName(deploymentUnit);
-        return this.secureDeployments.get(deploymentName);
+        return this.secureDeployments.containsKey(deploymentName)
+          ? this.secureDeployments.get(deploymentName)
+          : new ModelNode();
     }
     
     // KEYCLOAK-3273: prefer module name if available
                diff --git a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakAdapterConfigService.java b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakAdapterConfigService.java
index 8214c3f..1ccd2a0 100755
--- a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakAdapterConfigService.java
+++ b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakAdapterConfigService.java
@@ -164,6 +164,9 @@ public final class KeycloakAdapterConfigService {
 
     protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
         ModelNode deployment = getSecureDeployment(deploymentUnit);
+        if (! deployment.isDefined()) {
+            return false;
+        }
         ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
         return resource.isDefined();
     }
@@ -201,7 +204,9 @@ public final class KeycloakAdapterConfigService {
 
     private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
         String deploymentName = preferredDeploymentName(deploymentUnit);
-        return this.secureDeployments.get(deploymentName);
+        return this.secureDeployments.containsKey(deploymentName)
+          ? this.secureDeployments.get(deploymentName)
+          : new ModelNode();
     }
     
     // KEYCLOAK-3273: prefer module name if available
                diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
index c30e3ed..e96a5e5 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakAdapterConfigService.java
@@ -164,6 +164,9 @@ public final class KeycloakAdapterConfigService {
 
     protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
         ModelNode deployment = getSecureDeployment(deploymentUnit);
+        if (! deployment.isDefined()) {
+            return false;
+        }
         ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
         return resource.isDefined();
     }
@@ -201,7 +204,9 @@ public final class KeycloakAdapterConfigService {
 
     private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
         String deploymentName = preferredDeploymentName(deploymentUnit);
-        return this.secureDeployments.get(deploymentName);
+        return this.secureDeployments.containsKey(deploymentName)
+          ? this.secureDeployments.get(deploymentName)
+          : new ModelNode();
     }
     
     // KEYCLOAK-3273: prefer module name if available
                diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
index 2a6e4d3..d4ddc02 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakSubsystemParser.java
@@ -85,11 +85,6 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
             def.parseAndSetParameter(reader.getElementText(), addRealm, reader);
         }
 
-        if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(addRealm)) {
-            //TODO: externalize the message
-            throw new XMLStreamException("truststore and truststore-password must be set if ssl-required is not none and disable-trust-maanger is false.");
-        }
-
         list.add(addRealm);
     }
 
@@ -113,15 +108,6 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
             def.parseAndSetParameter(reader.getElementText(), addSecureDeployment, reader);
         }
 
-
-        /**
-         * TODO need to check realm-ref first.
-        if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(addSecureDeployment)) {
-            //TODO: externalize the message
-            throw new XMLStreamException("truststore and truststore-password must be set if ssl-required is not none  and disable-trust-maanger is false.");
-        }
-         */
-
         // Must add credentials after the deployment is added.
         resourcesToAdd.add(addSecureDeployment);
         resourcesToAdd.addAll(credentialsToAdd);
                diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/RealmAddHandler.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/RealmAddHandler.java
index 49754d4..0f59c4e 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/RealmAddHandler.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/RealmAddHandler.java
@@ -48,10 +48,6 @@ public final class RealmAddHandler extends AbstractAddStepHandler {
             attrib.validateAndSet(operation, model);
         }
 
-        if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(model.clone())) {
-            //TODO: externalize message
-            throw new OperationFailedException("truststore and truststore-password must be set if ssl-required is not none and disable-trust-maanger is false.");
-        }
     }
 
     @Override
                diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
index 0244d47..f9f8a6a 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/SharedAttributeDefinitons.java
@@ -195,25 +195,6 @@ public class SharedAttributeDefinitons {
         ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE);
     }
 
-    /**
-     * truststore and truststore-password must be set if ssl-required is not none and disable-trust-manager is false.
-     *
-     * @param attributes The full set of attributes.
-     *
-     * @return <code>true</code> if the attributes are valid, <code>false</code> otherwise.
-     */
-    public static boolean validateTruststoreSetIfRequired(ModelNode attributes) {
-        if (isSet(attributes, DISABLE_TRUST_MANAGER)) {
-            return true;
-        }
-
-        if (isSet(attributes, SSL_REQUIRED) && attributes.get(SSL_REQUIRED.getName()).asString().equals("none")) {
-            return true;
-        }
-
-        return isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD);
-    }
-
     private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) {
         ModelNode attribute = attributes.get(def.getName());
 
                adapters/saml/undertow/pom.xml 6(+0 -6)
diff --git a/adapters/saml/undertow/pom.xml b/adapters/saml/undertow/pom.xml
index 8488fc4..142d78f 100755
--- a/adapters/saml/undertow/pom.xml
+++ b/adapters/saml/undertow/pom.xml
@@ -32,12 +32,6 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.jboss.logging</groupId>
-            <artifactId>jboss-logging</artifactId>
-            <version>${jboss.logging.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-saml-core</artifactId>
             <scope>provided</scope>
                diff --git a/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java
index 6558c41..0cd65e1 100755
--- a/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/ConfigPropertyRepresentation.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.representations.idm;
 
+import java.util.List;
+
 /**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
@@ -27,6 +29,7 @@ public class ConfigPropertyRepresentation {
     protected String helpText;
     protected String type;
     protected Object defaultValue;
+    protected List<String> options;
     protected boolean secret;
 
     public String getName() {
@@ -69,6 +72,14 @@ public class ConfigPropertyRepresentation {
         this.helpText = helpText;
     }
 
+    public List<String> getOptions() {
+        return options;
+    }
+
+    public void setOptions(List<String> options) {
+        this.options = options;
+    }
+
     public boolean isSecret() {
         return secret;
     }
                diff --git a/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
index a394b3c..681a03b 100644
--- a/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/idm/UserConsentRepresentation.java
@@ -35,6 +35,10 @@ public class UserConsentRepresentation {
     // Key is clientId, Value is list of granted roles of this client
     protected Map<String, List<String>> grantedClientRoles;
 
+    private Long createdDate;
+
+    private Long lastUpdatedDate;
+
     public String getClientId() {
         return clientId;
     }
@@ -66,4 +70,20 @@ public class UserConsentRepresentation {
     public void setGrantedClientRoles(Map<String, List<String>> grantedClientRoles) {
         this.grantedClientRoles = grantedClientRoles;
     }
+
+    public void setCreatedDate(Long createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public void setLastUpdatedDate(Long lastUpdatedDate) {
+        this.lastUpdatedDate = lastUpdatedDate;
+    }
+
+    public Long getLastUpdatedDate() {
+        return lastUpdatedDate;
+    }
 }
                dependencies/server-all/pom.xml 78(+11 -67)
diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml
index 16887c1..cc6073a 100755
--- a/dependencies/server-all/pom.xml
+++ b/dependencies/server-all/pom.xml
@@ -31,29 +31,17 @@
     <name>Keycloak Dependencies Server All</name>
 	<description />
 
-    <properties>
-        <!-- Drools dependencies versions -->
-        <version.org.eclipse.sisu>0.3.0.M1</version.org.eclipse.sisu>
-        <version.org.eclipse.aether>1.0.0.v20140518</version.org.eclipse.aether>
-        <version.org.apache.ant>1.8.3</version.org.apache.ant>
-        <version.org.antlr>3.5</version.org.antlr>
-        <version.aopalliance>1.0</version.aopalliance>
-        <version.org.apache.maven>3.2.5</version.org.apache.maven>
-        <version.org.mvel>2.2.8.Final</version.org.mvel>
-        <version.org.sonatype.plexus.plexus-cipher>1.7</version.org.sonatype.plexus.plexus-cipher>
-        <version.org.codehaus.plexus.plexus-classworlds>2.5.2</version.org.codehaus.plexus.plexus-classworlds>
-        <version.org.codehaus.plexus.plexus-component-annotations>1.5.5</version.org.codehaus.plexus.plexus-component-annotations>
-        <version.org.codehaus.plexus.plexus-interpolation>1.21</version.org.codehaus.plexus.plexus-interpolation>
-        <version.org.codehaus.plexus.plexus-sec-dispatcher>1.3</version.org.codehaus.plexus.plexus-sec-dispatcher>
-        <version.org.codehaus.plexus.plexus-utils>3.0.20</version.org.codehaus.plexus.plexus-utils>
-        <version.org.apache.maven.wagon>2.6</version.org.apache.maven.wagon>
-        <version.com.thoughtworks.xstream>1.4.7</version.com.thoughtworks.xstream>
-        <version.com.google.guava>13.0.1</version.com.google.guava>
-        <version.org.eclipse.jdt.core.compiler>4.4.2</version.org.eclipse.jdt.core.compiler>
-        <version.com.lowagie>2.1.2</version.com.lowagie>
-        <version.org.sonatype.sisu>3.2.3</version.org.sonatype.sisu>
-        <version.com.google.inject.extensions.guice-servlet>3.0</version.com.google.inject.extensions.guice-servlet>
-    </properties>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.jboss.integration-platform</groupId>
+                <artifactId>jboss-integration-platform-bom</artifactId>
+                <type>pom</type>
+                <scope>import</scope>
+                <version>${version.jboss-integration-platform}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 
     <dependencies>
         <dependency>
@@ -158,122 +146,98 @@
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-api</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-connector-basic</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-spi</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-impl</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-transport-file</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-transport-http</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-transport-wagon</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.aether</groupId>
             <artifactId>aether-util</artifactId>
-            <version>${version.org.eclipse.aether}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.ant</groupId>
             <artifactId>ant</artifactId>
-            <version>${version.org.apache.ant}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.ant</groupId>
             <artifactId>ant-launcher</artifactId>
-            <version>${version.org.apache.ant}</version>
         </dependency>
         <dependency>
             <groupId>org.antlr</groupId>
             <artifactId>antlr-runtime</artifactId>
-            <version>${version.org.antlr}</version>
         </dependency>
         <dependency>
             <groupId>aopalliance</groupId>
             <artifactId>aopalliance</artifactId>
-            <version>${version.aopalliance}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-aether-provider</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-artifact</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-compat</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-core</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-model</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-model-builder</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-plugin-api</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-repository-metadata</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-settings</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-settings-builder</artifactId>
-            <version>${version.org.apache.maven}</version>
         </dependency>
         <dependency>
             <groupId>org.mvel</groupId>
             <artifactId>mvel2</artifactId>
-            <version>${version.org.mvel}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.sisu</groupId>
             <artifactId>org.eclipse.sisu.inject</artifactId>
-            <version>${version.org.eclipse.sisu}</version>
             <exclusions>
                 <exclusion>
                     <groupId>com.google.inject</groupId>
@@ -282,14 +246,8 @@
             </exclusions>
         </dependency>
         <dependency>
-            <groupId>com.google.inject.extensions</groupId>
-            <artifactId>guice-servlet</artifactId>
-            <version>${version.com.google.inject.extensions.guice-servlet}</version>
-        </dependency>
-        <dependency>
             <groupId>org.eclipse.sisu</groupId>
             <artifactId>org.eclipse.sisu.plexus</artifactId>
-            <version>${version.org.eclipse.sisu}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.sonatype.sisu</groupId>
@@ -300,62 +258,50 @@
         <dependency>
             <groupId>org.sonatype.plexus</groupId>
             <artifactId>plexus-cipher</artifactId>
-            <version>${version.org.sonatype.plexus.plexus-cipher}</version>
         </dependency>
         <dependency>
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-classworlds</artifactId>
-            <version>${version.org.codehaus.plexus.plexus-classworlds}</version>
         </dependency>
         <dependency>
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-component-annotations</artifactId>
-            <version>${version.org.codehaus.plexus.plexus-component-annotations}</version>
         </dependency>
         <dependency>
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-interpolation</artifactId>
-            <version>${version.org.codehaus.plexus.plexus-interpolation}</version>
         </dependency>
         <dependency>
             <groupId>org.sonatype.plexus</groupId>
             <artifactId>plexus-sec-dispatcher</artifactId>
-            <version>${version.org.codehaus.plexus.plexus-sec-dispatcher}</version>
         </dependency>
         <dependency>
             <groupId>org.codehaus.plexus</groupId>
             <artifactId>plexus-utils</artifactId>
-            <version>${version.org.codehaus.plexus.plexus-utils}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven.wagon</groupId>
             <artifactId>wagon-http</artifactId>
-            <version>${version.org.apache.maven.wagon}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven.wagon</groupId>
             <artifactId>wagon-http-shared</artifactId>
-            <version>${version.org.apache.maven.wagon}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven.wagon</groupId>
             <artifactId>wagon-provider-api</artifactId>
-            <version>${version.org.apache.maven.wagon}</version>
         </dependency>
         <dependency>
             <groupId>com.thoughtworks.xstream</groupId>
             <artifactId>xstream</artifactId>
-            <version>${version.com.thoughtworks.xstream}</version>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>${version.com.google.guava}</version>
         </dependency>
         <dependency>
             <groupId>org.eclipse.jdt.core.compiler</groupId>
             <artifactId>ecj</artifactId>
-            <version>${version.org.eclipse.jdt.core.compiler}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
@@ -368,7 +314,6 @@
         <dependency>
             <groupId>com.lowagie</groupId>
             <artifactId>itext</artifactId>
-            <version>${version.com.lowagie}</version>
             <exclusions>
                 <exclusion>
                     <groupId>bouncycastle</groupId>
@@ -387,7 +332,6 @@
         <dependency>
             <groupId>org.sonatype.sisu</groupId>
             <artifactId>sisu-guice</artifactId>
-            <version>${version.org.sonatype.sisu}</version>
             <classifier>no_aop</classifier>
         </dependency>
     </dependencies>
                distribution/demo-dist/pom.xml 44(+19 -25)
diff --git a/distribution/demo-dist/pom.xml b/distribution/demo-dist/pom.xml
index 76c002e..1e77622 100755
--- a/distribution/demo-dist/pom.xml
+++ b/distribution/demo-dist/pom.xml
@@ -151,6 +151,24 @@
                             </artifactItems>
                         </configuration>
                     </execution>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-wildfly-server-subsystem</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <includes>default-config/*.xml</includes>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
                 </executions>
             </plugin>
 
@@ -202,31 +220,7 @@
                     </execution>
                 </executions>
             </plugin>
-            
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>unpack</id>
-                        <phase>compile</phase>
-                        <goals>
-                            <goal>unpack</goal>
-                        </goals>
-                        <configuration>
-                            <artifactItems>
-                                <artifactItem>
-                                    <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-wildfly-server-subsystem</artifactId>
-                                    <version>${project.version}</version>
-                                    <type>jar</type>
-                                    <includes>default-config/*.xml</includes>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
+
         </plugins>
     </build>
 
                diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
index 8cf1cde..4f351fd 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
@@ -27,11 +27,6 @@
     <dependencies>
         <module name="org.keycloak.keycloak-common" services="import"/>
         <module name="org.keycloak.keycloak-core" services="import"/>
-        <module name="org.keycloak.keycloak-themes">
-            <imports>
-                <include path="META-INF"/>
-            </imports>
-        </module>
         <module name="org.keycloak.keycloak-js-adapter" services="import"/>
         <module name="org.keycloak.keycloak-kerberos-federation" services="import"/>
         <module name="org.keycloak.keycloak-ldap-federation" services="import"/>
                diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-extensions/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-extensions/main/module.xml
index 3f0470c..d785cb7 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-extensions/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-extensions/main/module.xml
@@ -29,7 +29,6 @@
         <module name="org.keycloak.keycloak-core"/>
         <module name="org.keycloak.keycloak-server-spi"/>
         <module name="org.keycloak.keycloak-services"/>
-        <module name="org.keycloak.keycloak-themes"/>
         <module name="org.jboss.modules"/>
     </dependencies>
 </module>
                diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/sonatype/sisu/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/sonatype/sisu/main/module.xml
index 8808d91..866a618 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/sonatype/sisu/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/sonatype/sisu/main/module.xml
@@ -20,7 +20,6 @@
         <property name="jboss.api" value="private"/>
     </properties>
     <resources>
-        <artifact name="${com.google.inject.extensions:guice-servlet}"/>
         <artifact name="${org.sonatype.sisu:sisu-guice::no_aop}"/>
     </resources>
     <dependencies>
                diff --git a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml
index 0950a3b..c8de616 100755
--- a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml
+++ b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml
@@ -80,10 +80,6 @@
             <artifactId>keycloak-tomcat-adapter-spi</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-jboss-adapter-core</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
         </dependency>
                diff --git a/distribution/server-dist/assembly.xml b/distribution/server-dist/assembly.xml
index 9e24567..0e58c83 100755
--- a/distribution/server-dist/assembly.xml
+++ b/distribution/server-dist/assembly.xml
@@ -46,6 +46,7 @@
                 <exclude>appclient/**</exclude>
                 <exclude>copyright.txt</exclude>
                 <exclude>README.txt</exclude>
+                <exclude>themes/**</exclude>
             </excludes>
         </fileSet>
         <fileSet>
@@ -57,6 +58,14 @@
             <fileMode>0755</fileMode>
         </fileSet>
         <fileSet>
+            <directory>target/${project.build.finalName}</directory>
+            <outputDirectory/>
+            <includes>
+                <include>themes/**</include>
+            </includes>
+            <fileMode>0444</fileMode>
+        </fileSet>
+        <fileSet>
             <directory>src/main/welcome-content</directory>
             <outputDirectory>welcome-content</outputDirectory>
             <includes>
                diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/app/app.component.ts b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.component.ts
index a6955e7..cd8ba04 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/app/app.component.ts
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.component.ts
@@ -39,27 +39,9 @@ export class AppComponent {
   }
 
   reloadData() {
-    //angular dont have http interceptor yet
-
-    this.kc.getToken()
-      .then(token => {
-        let headers = new Headers({
-          'Accept': 'application/json',
-          'Authorization': 'Bearer ' + token
-        });
-
-        let options = new RequestOptions({ headers });
-
-        this.http.get('/database/products', options)
-          .map(res => res.json())
-          .subscribe(prods => this.products = prods,
-            error => console.log(error));
-      })
-      .catch(error => console.log(error));
-  }
-
-  private handleError(error: Response) {
-    console.error(error);
-    return Observable.throw(error.json().error || 'Server error');
+    this.http.get('/database/products')
+      .map(res => res.json())
+      .subscribe(prods => this.products = prods,
+        error => console.log(error));
   }
 }
                diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts
index 6d2891f..fd6075f 100644
--- a/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/app/app.module.ts
@@ -1,8 +1,9 @@
 import {NgModule} from "@angular/core";
 import {BrowserModule} from "@angular/platform-browser";
-import {HttpModule} from "@angular/http";
+import {HttpModule, Http, XHRBackend, RequestOptions} from '@angular/http';
 import {KeycloakService} from "./keycloak.service";
 import {AppComponent} from "./app.component";
+import {KeycloakHttp} from "./keycloak.http";
 
 @NgModule({
   imports: [
@@ -14,7 +15,18 @@ import {AppComponent} from "./app.component";
   ],
   providers: [
     KeycloakService,
+
+    {
+      provide: Http,
+      useFactory:
+      (
+        backend: XHRBackend,
+        defaultOptions: RequestOptions,
+        keycloakService: KeycloakService
+      ) => new KeycloakHttp(backend, defaultOptions, keycloakService),
+      deps: [XHRBackend, RequestOptions, KeycloakService]
+    }
   ],
   bootstrap: [ AppComponent ]
 })
-export class AppModule {}
+export class AppModule {}
\ No newline at end of file
                diff --git a/examples/demo-template/angular2-product-app/src/main/webapp/app/keycloak.http.ts b/examples/demo-template/angular2-product-app/src/main/webapp/app/keycloak.http.ts
new file mode 100644
index 0000000..a7af71a
--- /dev/null
+++ b/examples/demo-template/angular2-product-app/src/main/webapp/app/keycloak.http.ts
@@ -0,0 +1,116 @@
+import {Injectable} from "@angular/core";
+import {Http, Request, ConnectionBackend, RequestOptions, RequestOptionsArgs, Response, Headers} from "@angular/http";
+
+import {KeycloakService} from "./keycloak.service";
+import {Observable} from 'rxjs/Rx';
+
+/**
+ * This provides a wrapper over the ng2 Http class that insures tokens are refreshed on each request.
+ */
+@Injectable()
+export class KeycloakHttp extends Http {
+    constructor(_backend: ConnectionBackend, _defaultOptions: RequestOptions, private _keycloakService:KeycloakService) {
+        super(_backend, _defaultOptions);
+    }
+
+    private setToken(options: RequestOptionsArgs) {
+
+        if (options == null || KeycloakService.auth == null || KeycloakService.auth.authz == null || KeycloakService.auth.authz.token == null) {
+            console.log("Need a token, but no token is available, not setting bearer token.");
+            return;
+        }
+
+        options.headers.set('Authorization', 'Bearer ' + KeycloakService.auth.authz.token);
+    }
+
+    private configureRequest(f:Function, url:string | Request, options:RequestOptionsArgs, body?: any):Observable<Response> {
+        let tokenPromise:Promise<string> = this._keycloakService.getToken();
+        let tokenObservable:Observable<string> = Observable.fromPromise(tokenPromise);
+        let tokenUpdateObservable:Observable<any> = Observable.create((observer) => {
+            if (options == null) {
+                let headers = new Headers();
+                options = new RequestOptions({ headers: headers });
+            }
+
+            this.setToken(options);
+            observer.next();
+            observer.complete();
+        });
+        let requestObservable:Observable<Response> = Observable.create((observer) => {
+            let result;
+            if (body) {
+                result = f.apply(this, [url, body, options]);
+            } else {
+                result = f.apply(this, [url, options]);
+            }
+
+            result.subscribe((response) => {
+                observer.next(response);
+                observer.complete();
+            });
+        });
+
+        return <Observable<Response>>Observable
+            .merge(tokenObservable, tokenUpdateObservable, requestObservable, 1) // Insure no concurrency in the merged Observables
+            .filter((response) => response instanceof Response);
+    }
+
+    /**
+     * Performs any type of http request. First argument is required, and can either be a url or
+     * a {@link Request} instance. If the first argument is a url, an optional {@link RequestOptions}
+     * object can be provided as the 2nd argument. The options object will be merged with the values
+     * of {@link BaseRequestOptions} before performing the request.
+     */
+    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.request, url, options);
+    }
+
+    /**
+     * Performs a request with `get` http method.
+     */
+    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.get, url, options);
+    }
+
+    /**
+     * Performs a request with `post` http method.
+     */
+    post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.post, url, options, body);
+    }
+
+    /**
+     * Performs a request with `put` http method.
+     */
+    put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.put, url, options, body);
+    }
+
+    /**
+     * Performs a request with `delete` http method.
+     */
+    delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.delete, url, options);
+    }
+
+    /**
+     * Performs a request with `patch` http method.
+     */
+    patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.patch, url, options, body);
+    }
+
+    /**
+     * Performs a request with `head` http method.
+     */
+    head(url: string, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.head, url, options);
+    }
+
+    /**
+     * Performs a request with `options` http method.
+     */
+    options(url: string, options?: RequestOptionsArgs): Observable<Response> {
+        return this.configureRequest(super.options, url, options);
+    }
+}
                diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/AbstractLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/AbstractLDAPFederationMapperFactory.java
index d681125..ccd4aa6 100755
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/AbstractLDAPFederationMapperFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/AbstractLDAPFederationMapperFactory.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.federation.ldap.mappers;
 
+import java.util.List;
+
 import org.keycloak.Config;
 import org.keycloak.federation.ldap.LDAPFederationProvider;
 import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
@@ -75,13 +77,13 @@ public abstract class AbstractLDAPFederationMapperFactory implements UserFederat
     public void close() {
     }
 
-    public static ProviderConfigProperty createConfigProperty(String name, String label, String helpText, String type, Object defaultValue) {
+    public static ProviderConfigProperty createConfigProperty(String name, String label, String helpText, String type, List<String> options) {
         ProviderConfigProperty configProperty = new ProviderConfigProperty();
         configProperty.setName(name);
         configProperty.setLabel(label);
         configProperty.setHelpText(helpText);
         configProperty.setType(type);
-        configProperty.setDefaultValue(defaultValue);
+        configProperty.setOptions(options);
         return configProperty;
     }
 
                diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java
index e27f3ef..460ab62 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/group/GroupLDAPFederationMapper.java
@@ -48,6 +48,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.keycloak.models.RoleModel;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -561,6 +562,11 @@ public class GroupLDAPFederationMapper extends AbstractLDAPFederationMapper impl
         }
 
         @Override
+        public boolean hasRole(RoleModel role) {
+            return super.hasRole(role) || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
+        }
+
+        @Override
         public Set<GroupModel> getGroups() {
             Set<GroupModel> ldapGroupMappings = getLDAPGroupMappingsConverted();
             if (config.getMode() == LDAPGroupMapperMode.LDAP_ONLY) {
                diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java
index 2a23001..9d6e2a1 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/membership/role/RoleLDAPFederationMapper.java
@@ -348,7 +348,8 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper imple
         @Override
         public boolean hasRole(RoleModel role) {
             Set<RoleModel> roles = getRoleMappings();
-            return KeycloakModelUtils.hasRole(roles, role);
+            return KeycloakModelUtils.hasRole(roles, role)
+              || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
         }
 
         @Override
                diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
index e57d456..4b24bd1 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedUserConsent.java
@@ -32,6 +32,8 @@ public class CachedUserConsent {
     private final String clientDbId;
     private final Set<ProtocolMapperModel> protocolMappers = new HashSet<>();
     private final Set<String> roleIds = new HashSet<>();
+    private final Long createdDate;
+    private final Long lastUpdatedDate;
 
     public CachedUserConsent(UserConsentModel consentModel) {
         this.clientDbId = consentModel.getClient().getId();
@@ -39,6 +41,8 @@ public class CachedUserConsent {
         for (RoleModel role : consentModel.getGrantedRoles()) {
             this.roleIds.add(role.getId());
         }
+        this.createdDate = consentModel.getCreatedDate();
+        this.lastUpdatedDate = consentModel.getLastUpdatedDate();
     }
 
     public String getClientDbId() {
@@ -52,4 +56,12 @@ public class CachedUserConsent {
     public Set<String> getRoleIds() {
         return roleIds;
     }
+
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public Long getLastUpdatedDate() {
+        return lastUpdatedDate;
+    }
 }
                diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
index edbc186..6030a66 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserAdapter.java
@@ -301,7 +301,7 @@ public class UserAdapter implements CachedUserModel {
         for (RoleModel mapping: mappings) {
            if (mapping.hasRole(role)) return true;
         }
-        return false;
+        return KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
     }
 
     @Override
                diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index 9fa874d..547419e 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -555,6 +555,8 @@ public class UserCacheSession implements UserCache {
         }
 
         UserConsentModel consentModel = new UserConsentModel(client);
+        consentModel.setCreatedDate(cachedConsent.getCreatedDate());
+        consentModel.setLastUpdatedDate(cachedConsent.getLastUpdatedDate());
 
         for (String roleId : cachedConsent.getRoleIds()) {
             RoleModel role = session.realms().getRoleById(roleId, realm);
                diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
index 957c79a..f3b304d 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
@@ -33,11 +33,19 @@ import org.keycloak.models.KeycloakSession;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.Writer;
 import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.util.List;
 import java.util.Set;
 import liquibase.LabelExpression;
+import liquibase.database.Database;
+import liquibase.exception.DatabaseException;
+import liquibase.executor.Executor;
+import liquibase.executor.ExecutorService;
+import liquibase.executor.LoggingExecutor;
+import liquibase.statement.core.CreateDatabaseChangeLogTableStatement;
+import liquibase.util.StreamUtil;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -96,7 +104,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
 
 
     protected void updateChangeSet(Liquibase liquibase, String changelog, File exportFile) throws LiquibaseException, IOException {
-        List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression());
+        List<ChangeSet> changeSets = getChangeSets(liquibase);
         if (!changeSets.isEmpty()) {
             List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
             if (ranChangeSets.isEmpty()) {
@@ -110,7 +118,12 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
             }
 
             if (exportFile != null) {
-                liquibase.update((Contexts) null, new FileWriter(exportFile));
+                try (Writer exportWriter = new FileWriter(exportFile)) {
+                    if (ranChangeSets.isEmpty()) {
+                        outputChangeLogTableCreationScript(liquibase, exportWriter);
+                    }
+                    liquibase.update((Contexts) null, new LabelExpression(), exportWriter, false);
+                }
             } else {
                 liquibase.update((Contexts) null);
             }
@@ -125,6 +138,27 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
         }
     }
 
+    private void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter) throws DatabaseException {
+        Database database = liquibase.getDatabase();
+
+        Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
+        LoggingExecutor executor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), exportWriter, database);
+        ExecutorService.getInstance().setExecutor(database, executor);
+
+        executor.comment("*********************************************************************");
+        executor.comment("* Keycloak database creation script - apply this script to empty DB *");
+        executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
+
+        executor.execute(new CreateDatabaseChangeLogTableStatement());
+        // DatabaseChangeLogLockTable is created before this code is executed and recreated if it does not exist automatically
+        // in org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService.init() called indirectly from
+        // KeycloakApplication constructor (search for waitForLock() call). Hence it is not included in the creation script.
+
+        executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
+
+        ExecutorService.getInstance().setExecutor(database, oldTemplate);
+    }
+
     @Override
     public Status validate(Connection connection, String defaultSchema) {
         logger.debug("Validating if database is updated");
@@ -160,7 +194,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
     }
 
     protected Status validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
-        List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression());
+        List<ChangeSet> changeSets = getChangeSets(liquibase);
+
         if (!changeSets.isEmpty()) {
             if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) {
                 return Status.EMPTY;
@@ -174,6 +209,15 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
         }
     }
 
+    @SuppressWarnings("unchecked")
+    private List<ChangeSet> getChangeSets(Liquibase liquibase) {
+        // TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
+        // TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
+        // List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
+        Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
+        return Reflections.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
+    }
+
     private Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema) throws LiquibaseException {
         LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
         return liquibaseProvider.getLiquibase(connection, defaultSchema);
                diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
index 34c272a..c2b7b02 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserConsentEntity.java
@@ -68,6 +68,12 @@ public class UserConsentEntity {
     @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
     Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<UserConsentProtocolMapperEntity>();
 
+    @Column(name = "CREATED_DATE")
+    private Long createdDate;
+
+    @Column(name = "LAST_UPDATED_DATE")
+    private Long lastUpdatedDate;
+
     public String getId() {
         return id;
     }
@@ -108,6 +114,22 @@ public class UserConsentEntity {
         this.grantedProtocolMappers = grantedProtocolMappers;
     }
 
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public void setCreatedDate(Long createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    public Long getLastUpdatedDate() {
+        return lastUpdatedDate;
+    }
+
+    public void setLastUpdatedDate(Long lastUpdatedDate) {
+        this.lastUpdatedDate = lastUpdatedDate;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -125,5 +147,4 @@ public class UserConsentEntity {
     public int hashCode() {
         return id.hashCode();
     }
-
 }
                diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index 0336631..bd03727 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -18,6 +18,7 @@
 package org.keycloak.models.jpa;
 
 import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.common.util.Time;
 import org.keycloak.component.ComponentModel;
 import org.keycloak.credential.CredentialModel;
 import org.keycloak.credential.UserCredentialStore;
@@ -201,10 +202,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
             throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
         }
 
+        long currentTime = Time.currentTimeMillis();
+
         consentEntity = new UserConsentEntity();
         consentEntity.setId(KeycloakModelUtils.generateId());
         consentEntity.setUser(em.getReference(UserEntity.class, userId));
         consentEntity.setClientId(clientId);
+        consentEntity.setCreatedDate(currentTime);
+        consentEntity.setLastUpdatedDate(currentTime);
         em.persist(consentEntity);
         em.flush();
 
@@ -277,6 +282,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
             throw new ModelException("Client with id " + entity.getClientId() + " is not available");
         }
         UserConsentModel model = new UserConsentModel(client);
+        model.setCreatedDate(entity.getCreatedDate());
+        model.setLastUpdatedDate(entity.getLastUpdatedDate());
 
         Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
         if (grantedRoleEntities != null) {
@@ -346,6 +353,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
             em.remove(toRemove);
         }
 
+        consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
+
         em.flush();
     }
 
                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 7c5fe1f..5ee5490 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
@@ -352,7 +352,8 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
     @Override
     public boolean hasRole(RoleModel role) {
         Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
+        return KeycloakModelUtils.hasRole(roles, role)
+          || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
     }
 
     protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) {
                diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
index e6d2753..cc4c9ff 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
@@ -36,4 +36,5 @@
     <include file="META-INF/jpa-changelog-authz-master.xml"/>
     <include file="META-INF/jpa-changelog-2.1.0.xml"/>
     <include file="META-INF/jpa-changelog-2.2.0.xml"/>
+    <include file="META-INF/jpa-changelog-2.3.0.xml"/>
 </databaseChangeLog>
                diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
index bc2ef13..579aa04 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.3.0.xml
@@ -31,6 +31,7 @@
         </createTable>
          <addPrimaryKey columnNames="ID" constraintName="CONSTR_FEDERATED_USER" tableName="FEDERATED_USER"/>
 
+         <dropDefaultValue tableName="USER_ENTITY" columnName="TOTP" />
          <dropColumn tableName="USER_ENTITY" columnName="TOTP" />
 
          <addColumn tableName="IDENTITY_PROVIDER">
@@ -47,7 +48,11 @@
          <dropColumn tableName="REALM" columnName="PUBLIC_KEY" />
          <dropColumn tableName="REALM" columnName="CERTIFICATE" />
 
-     </changeSet>
+         <addColumn tableName="USER_CONSENT">
+             <column name="CREATED_DATE" type="BIGINT"/>
+             <column name="LAST_UPDATED_DATE" type="BIGINT"/>
+         </addColumn>
 
+     </changeSet>
 
 </databaseChangeLog>
\ No newline at end of file
                diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
index cb27cf5..7b46c0c 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
@@ -21,6 +21,7 @@ import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.common.util.Time;
 import org.keycloak.component.ComponentModel;
 import org.keycloak.connections.mongo.api.MongoStore;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
@@ -524,9 +525,13 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
             throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
         }
 
+        long currentTime = Time.currentTimeMillis();
+
         MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
         consentEntity.setUserId(userId);
         consentEntity.setClientId(clientId);
+        consentEntity.setCreatedDate(currentTime);
+        consentEntity.setLastUpdatedDate(currentTime);
         fillEntityFromModel(consent, consentEntity);
         getMongoStore().insertEntity(consentEntity, invocationContext);
     }
@@ -568,6 +573,8 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
             throw new ModelException("Client with id " + entity.getClientId() + " is not available");
         }
         UserConsentModel model = new UserConsentModel(client);
+        model.setCreatedDate(entity.getCreatedDate());
+        model.setLastUpdatedDate(entity.getLastUpdatedDate());
 
         for (String roleId : entity.getGrantedRoles()) {
             RoleModel roleModel = realm.getRoleById(roleId);
@@ -596,6 +603,7 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
             protMapperIds.add(protMapperModel.getId());
         }
         consentEntity.setGrantedProtocolMappers(protMapperIds);
+        consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
     }
 
     @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 5453c0b..972f440 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
@@ -268,7 +268,8 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
     @Override
     public boolean hasRole(RoleModel role) {
         Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
+        return KeycloakModelUtils.hasRole(roles, role)
+          || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
     }
 
     @Override
                diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
index c60faee..1ca9e64 100644
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/entities/UserConsentEntity.java
@@ -29,6 +29,8 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
     private String clientId;
     private List<String> grantedRoles = new ArrayList<String>();
     private List<String> grantedProtocolMappers = new ArrayList<String>();
+    private Long createdDate;
+    private Long lastUpdatedDate;
 
     public String getUserId() {
         return userId;
@@ -61,4 +63,20 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
     public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
         this.grantedProtocolMappers = grantedProtocolMappers;
     }
+
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public void setCreatedDate(Long createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    public Long getLastUpdatedDate() {
+        return lastUpdatedDate;
+    }
+
+    public void setLastUpdatedDate(Long lastUpdatedDate) {
+        this.lastUpdatedDate = lastUpdatedDate;
+    }
 }
                pom.xml 1(+1 -0)
diff --git a/pom.xml b/pom.xml
index 81bbbec..d928b9c 100755
--- a/pom.xml
+++ b/pom.xml
@@ -80,6 +80,7 @@
 
         <!-- Authorization Drools Policy Provider -->
         <version.org.drools>6.4.0.Final</version.org.drools>
+        <version.jboss-integration-platform>6.0.6.Final</version.jboss-integration-platform>
 
         <!-- Others -->
         <apacheds.version>2.0.0-M17</apacheds.version>
                diff --git a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
index e2b55e1..a21aa65 100755
--- a/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
+++ b/server-spi/src/main/java/org/keycloak/migration/MigrationModelManager.java
@@ -30,6 +30,7 @@ import org.keycloak.migration.migrators.MigrateTo1_9_2;
 import org.keycloak.migration.migrators.MigrateTo2_0_0;
 import org.keycloak.migration.migrators.MigrateTo2_1_0;
 import org.keycloak.migration.migrators.MigrateTo2_2_0;
+import org.keycloak.migration.migrators.MigrateTo2_3_0;
 import org.keycloak.migration.migrators.Migration;
 import org.keycloak.models.KeycloakSession;
 
@@ -53,6 +54,7 @@ public class MigrationModelManager {
         new MigrateTo2_0_0(),
         new MigrateTo2_1_0(),
         new MigrateTo2_2_0(),
+        new MigrateTo2_3_0(),
     };
 
     public static void migrate(KeycloakSession session) {
                diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java
new file mode 100644
index 0000000..80862ca
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_3_0.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.migration.migrators;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.keycloak.migration.ModelVersion;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientTemplateModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperContainerModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MigrateTo2_3_0 implements Migration {
+
+    public static final ModelVersion VERSION = new ModelVersion("2.3.0");
+
+    @Override
+    public void migrate(KeycloakSession session) {
+        for (RealmModel realm : session.realms().getRealms()) {
+            for (ClientModel client : realm.getClients()) {
+                updateProtocolMappers(client);
+            }
+
+            for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
+                updateProtocolMappers(clientTemplate);
+            }
+        }
+    }
+
+    private void updateProtocolMappers(ProtocolMapperContainerModel client) {
+        List<ProtocolMapperModel> toUpdate = new LinkedList<>();
+        for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
+            if (!mapper.getConfig().containsKey("userinfo.token.claim") && mapper.getConfig().containsKey("id.token.claim")) {
+                mapper.getConfig().put("userinfo.token.claim", mapper.getConfig().get("id.token.claim"));
+                toUpdate.add(mapper);
+            }
+        }
+
+        for (ProtocolMapperModel mapper : toUpdate) {
+            client.updateProtocolMapper(mapper);
+        }
+    }
+
+    @Override
+    public ModelVersion getVersion() {
+        return VERSION;
+    }
+}
                diff --git a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
index 1a8d974..cb10891 100755
--- a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -73,6 +73,8 @@ public interface KeycloakSession {
 
     <T extends Provider> Set<T> getAllProviders(Class<T> clazz);
 
+    Class<? extends Provider> getProviderClass(String providerClassName);
+
     Object getAttribute(String attribute);
     Object removeAttribute(String attribute);
     void setAttribute(String name, Object value);
                diff --git a/server-spi/src/main/java/org/keycloak/models/RoleMapperModel.java b/server-spi/src/main/java/org/keycloak/models/RoleMapperModel.java
index fd25372..85f1fd3 100755
--- a/server-spi/src/main/java/org/keycloak/models/RoleMapperModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/RoleMapperModel.java
@@ -28,8 +28,24 @@ public interface RoleMapperModel {
 
     Set<RoleModel> getClientRoleMappings(ClientModel app);
 
+    /**
+     * Returns {@code true} if this object is directly or indirectly assigned the given role, {@code false} otherwise.
+     * <p>
+     * For example, {@code true} is returned for hasRole(R) if:
+     * <ul>
+     *  <li>R is directly assigned to this object</li>
+     *  <li>R is not assigned to this object but this object belongs to a group G which is assigned the role R</li>
+     *  <li>R is not assigned to this object but this object belongs to a group G, and G belongs to group H which is assigned the role R</li>
+     * </ul>
+     * @param role
+     * @return see description
+     */
     boolean hasRole(RoleModel role);
 
+    /**
+     * Grants the given role to this object.
+     * @param role
+     */
     void grantRole(RoleModel role);
 
     Set<RoleModel> getRoleMappings();
                diff --git a/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java b/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
index d3c295b..847696d 100644
--- a/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserConsentModel.java
@@ -28,6 +28,8 @@ public class UserConsentModel {
     private final ClientModel client;
     private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
     private Set<RoleModel> roles = new HashSet<RoleModel>();
+    private Long createdDate;
+    private Long lastUpdatedDate;
 
     public UserConsentModel(ClientModel client) {
         this.client = client;
@@ -67,4 +69,19 @@ public class UserConsentModel {
         return false;
     }
 
+    public Long getCreatedDate() {
+        return createdDate;
+    }
+
+    public void setCreatedDate(Long createdDate) {
+        this.createdDate = createdDate;
+    }
+
+    public Long getLastUpdatedDate() {
+        return lastUpdatedDate;
+    }
+
+    public void setLastUpdatedDate(Long lastUpdatedDate) {
+        this.lastUpdatedDate = lastUpdatedDate;
+    }
 }
                diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ComponentUtil.java b/server-spi/src/main/java/org/keycloak/models/utils/ComponentUtil.java
index a0d915e..507bfff 100644
--- a/server-spi/src/main/java/org/keycloak/models/utils/ComponentUtil.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/ComponentUtil.java
@@ -47,10 +47,8 @@ public class ComponentUtil {
     }
 
     public static ComponentFactory getComponentFactory(KeycloakSession session, ComponentModel component) {
-        Class<? extends Provider> provider;
-        try {
-            provider = (Class<? extends Provider>) Class.forName(component.getProviderType());
-        } catch (ClassNotFoundException e) {
+        Class<? extends Provider> provider = session.getProviderClass(component.getProviderType());
+        if (provider == null) {
             throw new RuntimeException("Invalid provider type '" + component.getProviderType() + "'");
         }
 
                diff --git a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
index 1eae859..230d15f 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -70,6 +70,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.stream.StreamSupport;
 
 /**
  * Set of helper methods, which are useful in various model implementations.
@@ -267,6 +268,43 @@ public final class KeycloakModelUtils {
     }
 
     /**
+     * Checks whether the {@code targetRole} is contained in the given group or its parents
+     * (if requested)
+     * @param group Group to check role for
+     * @param targetRole
+     * @param checkParentGroup When {@code true}, also parent group is recursively checked for role
+     * @return true if targetRole is in roles (directly or indirectly via composite role)
+     */
+    public static boolean hasRoleFromGroup(GroupModel group, RoleModel targetRole, boolean checkParentGroup) {
+        if (group.hasRole(targetRole))
+            return true;
+
+        if (checkParentGroup) {
+            GroupModel parent = group.getParent();
+            return parent != null && hasRoleFromGroup(parent, targetRole, true);
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the {@code targetRole} is contained in any of the {@code groups} or their parents
+     * (if requested)
+     * @param groups
+     * @param targetRole
+     * @param checkParentGroup When {@code true}, also parent group is recursively checked for role
+     * @return true if targetRole is in roles (directly or indirectly via composite role)
+     */
+    public static boolean hasRoleFromGroup(Iterable<GroupModel> groups, RoleModel targetRole, boolean checkParentGroup) {
+        if (groups == null) {
+            return false;
+        }
+
+        return StreamSupport.stream(groups.spliterator(), false)
+          .anyMatch(group -> hasRoleFromGroup(group, targetRole, checkParentGroup));
+    }
+
+    /**
      *
      * @param groups
      * @param targetGroup
                diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 8703a05..e647aec 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -710,6 +710,8 @@ public class ModelToRepresentation {
         consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
         consentRep.setGrantedRealmRoles(grantedRealmRoles);
         consentRep.setGrantedClientRoles(grantedClientRoles);
+        consentRep.setCreatedDate(model.getCreatedDate());
+        consentRep.setLastUpdatedDate(model.getLastUpdatedDate());
         return consentRep;
     }
 
@@ -780,6 +782,7 @@ public class ModelToRepresentation {
         propRep.setLabel(prop.getLabel());
         propRep.setType(prop.getType());
         propRep.setDefaultValue(prop.getDefaultValue());
+        propRep.setOptions(prop.getOptions());
         propRep.setHelpText(prop.getHelpText());
         propRep.setSecret(prop.isSecret());
         return propRep;
                diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 83dd805..f1e4ea7 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1605,6 +1605,8 @@ public class RepresentationToModel {
         }
 
         UserConsentModel consentModel = new UserConsentModel(client);
+        consentModel.setCreatedDate(consentRep.getCreatedDate());
+        consentModel.setLastUpdatedDate(consentRep.getLastUpdatedDate());
 
         if (consentRep.getGrantedRealmRoles() != null) {
             for (String roleName : consentRep.getGrantedRealmRoles()) {
                diff --git a/server-spi/src/main/java/org/keycloak/provider/ProviderConfigProperty.java b/server-spi/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
index 5b824b3..a6dbd77 100755
--- a/server-spi/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
+++ b/server-spi/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.provider;
 
+import java.util.List;
+
 /**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
@@ -46,6 +48,7 @@ public class ProviderConfigProperty {
     protected String helpText;
     protected String type = STRING_TYPE;
     protected Object defaultValue;
+    protected List<String> options;
     protected boolean secret;
 
     public ProviderConfigProperty() {
@@ -96,6 +99,14 @@ public class ProviderConfigProperty {
         this.defaultValue = defaultValue;
     }
 
+    public List<String> getOptions() {
+        return options;
+    }
+
+    public void setOptions(List<String> options) {
+        this.options = options;
+    }
+
     public String getHelpText() {
         return helpText;
     }
                diff --git a/server-spi/src/main/java/org/keycloak/provider/ProviderConfigurationBuilder.java b/server-spi/src/main/java/org/keycloak/provider/ProviderConfigurationBuilder.java
index 5382355..607a41b 100644
--- a/server-spi/src/main/java/org/keycloak/provider/ProviderConfigurationBuilder.java
+++ b/server-spi/src/main/java/org/keycloak/provider/ProviderConfigurationBuilder.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.provider;
 
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -43,14 +44,17 @@ public class ProviderConfigurationBuilder {
         return this;
     }
 
-    public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, boolean secret) {
+    public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, List<String> options, boolean secret) {
         ProviderConfigProperty property = new ProviderConfigProperty(name, label, helpText, type, defaultValue);
+        property.setOptions(options);
         property.setSecret(secret);
         properties.add(property);
         return this;
     }
-    public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue) {
-        properties.add(new ProviderConfigProperty(name, label, helpText, type, defaultValue));
+    public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, List<String> options) {
+        ProviderConfigProperty property = new ProviderConfigProperty(name, label, helpText, type, defaultValue);
+        property.setOptions(options);
+        properties.add(property);
         return this;
     }
 
@@ -65,6 +69,7 @@ public class ProviderConfigurationBuilder {
         private String helpText;
         private String type;
         private Object defaultValue;
+        private List<String> options;
         private boolean secret;
 
         public ProviderConfigPropertyBuilder name(String name) {
@@ -92,6 +97,11 @@ public class ProviderConfigurationBuilder {
             return this;
         }
 
+        public ProviderConfigPropertyBuilder options(String... options) {
+            this.options = Arrays.asList(options);
+            return this;
+        }
+
         public ProviderConfigPropertyBuilder secret(boolean secret) {
             this.secret = secret;
             return this;
@@ -104,6 +114,7 @@ public class ProviderConfigurationBuilder {
             property.setHelpText(helpText);
             property.setType(type);
             property.setDefaultValue(defaultValue);
+            property.setOptions(options);
             property.setSecret(secret);
             ProviderConfigurationBuilder.this.properties.add(property);
             return ProviderConfigurationBuilder.this;
                diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
index 49d2288..df6c37a 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
@@ -172,7 +172,8 @@ public abstract class AbstractUserAdapter implements UserModel {
     @Override
     public boolean hasRole(RoleModel role) {
         Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
+        return KeycloakModelUtils.hasRole(roles, role)
+          || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
     }
 
     @Override
                diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
index 592b9ba..865f454 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
@@ -177,7 +177,8 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
     @Override
     public boolean hasRole(RoleModel role) {
         Set<RoleModel> roles = getRoleMappings();
-        return KeycloakModelUtils.hasRole(roles, role);
+        return KeycloakModelUtils.hasRole(roles, role)
+          || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
     }
 
     @Override
                diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
index 7469511..3b409a0 100755
--- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
+++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
@@ -63,7 +64,7 @@ import java.util.Map;
  */
 public class AuthenticationProcessor {
     public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution";
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AuthenticationProcessor.class);
     protected RealmModel realm;
     protected UserSessionModel userSession;
     protected ClientSessionModel clientSession;
@@ -561,25 +562,25 @@ public class AuthenticationProcessor {
         if (failure instanceof AuthenticationFlowException) {
             AuthenticationFlowException e = (AuthenticationFlowException) failure;
             if (e.getError() == AuthenticationFlowError.INVALID_USER) {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.USER_NOT_FOUND);
                 return ErrorPage.error(session, Messages.INVALID_USER);
             } else if (e.getError() == AuthenticationFlowError.USER_DISABLED) {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.USER_DISABLED);
                 return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
             } else if (e.getError() == AuthenticationFlowError.USER_TEMPORARILY_DISABLED) {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.USER_TEMPORARILY_DISABLED);
                 return ErrorPage.error(session, Messages.INVALID_USER);
 
             } else if (e.getError() == AuthenticationFlowError.INVALID_CLIENT_SESSION) {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.INVALID_CODE);
                 return ErrorPage.error(session, Messages.INVALID_CODE);
 
             } else if (e.getError() == AuthenticationFlowError.EXPIRED_CODE) {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.EXPIRED_CODE);
                 return ErrorPage.error(session, Messages.EXPIRED_CODE);
 
@@ -604,13 +605,13 @@ public class AuthenticationProcessor {
                 return processor.authenticate();
 
             } else {
-                logger.failedAuthentication(e);
+                ServicesLogger.LOGGER.failedAuthentication(e);
                 event.error(Errors.INVALID_USER_CREDENTIALS);
                 return ErrorPage.error(session, Messages.INVALID_USER);
             }
 
         } else {
-            logger.failedAuthentication(failure);
+            ServicesLogger.LOGGER.failedAuthentication(failure);
             event.error(Errors.INVALID_USER_CREDENTIALS);
             return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
         }
@@ -620,7 +621,7 @@ public class AuthenticationProcessor {
     public Response handleClientAuthException(Exception failure) {
         if (failure instanceof AuthenticationFlowException) {
             AuthenticationFlowException e = (AuthenticationFlowException) failure;
-            logger.failedClientAuthentication(e);
+            ServicesLogger.LOGGER.failedClientAuthentication(e);
             if (e.getError() == AuthenticationFlowError.CLIENT_NOT_FOUND) {
                 event.error(Errors.CLIENT_NOT_FOUND);
                 return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Could not find client");
@@ -635,7 +636,7 @@ public class AuthenticationProcessor {
                 return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", e.getError().toString() + ": " + e.getMessage());
             }
         } else {
-            logger.errorAuthenticatingClient(failure);
+            ServicesLogger.LOGGER.errorAuthenticatingClient(failure);
             event.error(Errors.INVALID_CLIENT_CREDENTIALS);
             return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unexpected error when authenticating client: " + failure.getMessage());
         }
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
index 407f8cc..8234700 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpConfirmLinkAuthenticator.java
@@ -39,15 +39,13 @@ import javax.ws.rs.core.Response;
  */
 public class IdpConfirmLinkAuthenticator extends AbstractIdpAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     @Override
     protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
         ClientSessionModel clientSession = context.getClientSession();
 
         String existingUserInfo = clientSession.getNote(EXISTING_USER_INFO);
         if (existingUserInfo == null) {
-            logger.noDuplicationDetected();
+            ServicesLogger.LOGGER.noDuplicationDetected();
             context.attempted();
             return;
         }
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
index c39d975..9c35844 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpCreateUserIfUniqueAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.broker;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo;
 import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@@ -39,7 +40,7 @@ import java.util.Map;
  */
 public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static Logger logger = Logger.getLogger(IdpCreateUserIfUniqueAuthenticator.class);
 
 
     @Override
@@ -59,7 +60,7 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
 
         String username = getUsername(context, serializedCtx, brokerContext);
         if (username == null) {
-            logger.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username");
+            ServicesLogger.LOGGER.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username");
             context.getClientSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
             context.resetFlow();
             return;
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
index 936ac7b..420eb20 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.broker;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.AuthenticationFlowError;
 import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@@ -48,7 +49,7 @@ import java.util.concurrent.TimeUnit;
  */
 public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static Logger logger = Logger.getLogger(IdpEmailVerificationAuthenticator.class);
 
     @Override
     protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
@@ -57,7 +58,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator 
         ClientSessionModel clientSession = context.getClientSession();
 
         if (realm.getSmtpConfig().size() == 0) {
-            logger.smtpNotConfigured();
+            ServicesLogger.LOGGER.smtpNotConfigured();
             context.attempted();
             return;
         }
@@ -94,7 +95,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator 
         } catch (EmailException e) {
             event.error(Errors.EMAIL_SEND_FAILED);
 
-            logger.confirmBrokerEmailFailed(e);
+            ServicesLogger.LOGGER.confirmBrokerEmailFailed(e);
             Response challenge = context.form()
                     .setError(Messages.EMAIL_SENT_ERROR)
                     .createErrorPage();
@@ -137,7 +138,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator 
                 context.setUser(existingUser);
                 context.success();
             } else {
-                logger.keyParamDoesNotMatch();
+                ServicesLogger.LOGGER.keyParamDoesNotMatch();
                 Response challengeResponse = context.form()
                         .setError(Messages.INVALID_ACCESS_CODE)
                         .createErrorPage();
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
index 003983d..c58e3e1 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.broker;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
 import org.keycloak.broker.provider.BrokeredIdentityContext;
@@ -45,7 +46,7 @@ import java.util.List;
  */
 public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(IdpReviewProfileAuthenticator.class);
 
     @Override
     public boolean requiresUser() {
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java
index 4937db3..b293b71 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpReviewProfileAuthenticatorFactory.java
@@ -108,7 +108,8 @@ public class IdpReviewProfileAuthenticatorFactory implements AuthenticatorFactor
         property.setLabel("{{:: 'update-profile-on-first-login' | translate}}");
         property.setType(ProviderConfigProperty.LIST_TYPE);
         List<String> updateProfileValues = Arrays.asList(IdentityProviderRepresentation.UPFLM_ON, IdentityProviderRepresentation.UPFLM_MISSING, IdentityProviderRepresentation.UPFLM_OFF);
-        property.setDefaultValue(updateProfileValues);
+        property.setOptions(updateProfileValues);
+        property.setDefaultValue(IdentityProviderRepresentation.UPFLM_MISSING);
         property.setHelpText("Define conditions under which a user has to review and update his profile after first-time login. Value 'On' means that"
                 + " page for reviewing profile will be displayed and user can review and update his profile. Value 'off' means that page won't be displayed."
                 + " Value 'missing' means that page is displayed just when some required attribute is missing (wasn't downloaded from identity provider). Value 'missing' is the default one."
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
index 6c10318..f88b674 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.browser;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.AbstractFormAuthenticator;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.AuthenticationFlowError;
@@ -43,7 +44,7 @@ import java.util.List;
  */
 public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuthenticator {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(AbstractUsernameFormAuthenticator.class);
 
     public static final String REGISTRATION_FORM_ACTION = "registration_form";
     public static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME";
@@ -131,7 +132,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
         try {
             user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
         } catch (ModelDuplicateException mde) {
-            logger.modelDuplicateException(mde);
+            ServicesLogger.LOGGER.modelDuplicateException(mde);
 
             // Could happen during federation import
             if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ConditionalOtpFormAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ConditionalOtpFormAuthenticatorFactory.java
index f19cbb6..f04ed07 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ConditionalOtpFormAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ConditionalOtpFormAuthenticatorFactory.java
@@ -156,7 +156,7 @@ public class ConditionalOtpFormAuthenticatorFactory implements AuthenticatorFact
         defaultOutcome.setType(LIST_TYPE);
         defaultOutcome.setName(DEFAULT_OTP_OUTCOME);
         defaultOutcome.setLabel("Fallback OTP handling");
-        defaultOutcome.setDefaultValue(asList(SKIP, FORCE));
+        defaultOutcome.setOptions(asList(SKIP, FORCE));
         defaultOutcome.setHelpText("What to do in case of every check abstains. Defaults to force OTP authentication.");
 
         return asList(forceOtpUserAttribute, skipOtpRole, forceOtpRole, skipOtpForHttpHeader, forceOtpForHttpHeader, defaultOutcome);
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticatorFactory.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticatorFactory.java
index f9b2ff2..b2e8b98 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticatorFactory.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/ScriptBasedAuthenticatorFactory.java
@@ -20,10 +20,12 @@ import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.Authenticator;
 import org.keycloak.authentication.AuthenticatorFactory;
+import org.keycloak.common.Profile;
 import org.keycloak.common.util.StreamUtil;
 import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.EnvironmentDependentProviderFactory;
 import org.keycloak.provider.ProviderConfigProperty;
 
 import java.io.IOException;
@@ -41,7 +43,7 @@ import static org.keycloak.provider.ProviderConfigProperty.STRING_TYPE;
  *
  * @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a>
  */
-public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory {
+public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory, EnvironmentDependentProviderFactory {
 
     private static final Logger LOGGER = Logger.getLogger(ScriptBasedAuthenticatorFactory.class);
 
@@ -148,4 +150,9 @@ public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory {
 
         return asList(name, description, script);
     }
+
+    @Override
+    public boolean isSupported() {
+        return Profile.isPreviewEnabled();
+    }
 }
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
index c88f492..b7a8b62 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/SpnegoAuthenticator.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.browser;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.AuthenticationFlowError;
@@ -44,7 +45,7 @@ import java.util.Map;
  */
 public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator implements Authenticator{
     public static final String KERBEROS_DISABLED = "kerberos_disabled";
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(SpnegoAuthenticator.class);
 
     @Override
     public boolean requiresUser() {
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
index 3bd6345..4f8e2d1 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/UsernamePasswordForm.java
@@ -37,7 +37,7 @@ import javax.ws.rs.core.Response;
  * @version $Revision: 1 $
  */
 public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator implements Authenticator {
-    protected static ServicesLogger log = ServicesLogger.ROOT_LOGGER;
+    protected static ServicesLogger log = ServicesLogger.LOGGER;
 
     @Override
     public void action(AuthenticationFlowContext context) {
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
index b7ecb41..78f58da 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/ClientIdAndSecretAuthenticator.java
@@ -25,7 +25,6 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.util.BasicAuthHelper;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -49,8 +48,6 @@ import java.util.Set;
  */
 public class ClientIdAndSecretAuthenticator extends AbstractClientAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     public static final String PROVIDER_ID = "client-secret";
 
     public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
index 16a867d..2896c60 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
@@ -59,8 +59,6 @@ import org.keycloak.services.Urls;
  */
 public class JWTClientAuthenticator extends AbstractClientAuthenticator {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     public static final String PROVIDER_ID = "client-jwt";
     public static final String ATTR_PREFIX = "jwt.credential";
     public static final String CERTIFICATE_ATTR = "jwt.credential.certificate";
@@ -156,7 +154,7 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
 
             context.success();
         } catch (Exception e) {
-            logger.errorValidatingAssertion(e);
+            ServicesLogger.LOGGER.errorValidatingAssertion(e);
             Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client authentication with signed JWT failed: " + e.getMessage());
             context.failure(AuthenticationFlowError.INVALID_CLIENT_CREDENTIALS, challengeResponse);
         }
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
index 54bf8b9..d9e8c4b 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidateUsername.java
@@ -43,7 +43,6 @@ import java.util.List;
  */
 public class ValidateUsername extends AbstractDirectGrantAuthenticator {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
     public static final String PROVIDER_ID = "direct-grant-validate-username";
 
     @Override
@@ -63,7 +62,7 @@ public class ValidateUsername extends AbstractDirectGrantAuthenticator {
         try {
             user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
         } catch (ModelDuplicateException mde) {
-            logger.modelDuplicateException(mde);
+            ServicesLogger.LOGGER.modelDuplicateException(mde);
             Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_request", "Invalid user credentials");
             context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse);
             return;
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
index 3c575c8..d0919cc 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialChooseUser.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.resetcred;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.AuthenticationFlowError;
@@ -46,7 +47,7 @@ import java.util.List;
  */
 public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFactory {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ResetCredentialChooseUser.class);
 
     public static final String PROVIDER_ID = "reset-credentials-choose-user";
 
                diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
index da4e7c0..d7e3e74 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/resetcred/ResetCredentialEmail.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.authenticators.resetcred;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.AuthenticationFlowContext;
 import org.keycloak.authentication.AuthenticationFlowError;
@@ -53,7 +54,7 @@ import java.util.concurrent.TimeUnit;
 public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory {
     public static final String RESET_CREDENTIAL_SECRET = "RESET_CREDENTIAL_SECRET";
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ResetCredentialEmail.class);
 
     public static final String PROVIDER_ID = "reset-credential-email";
 
@@ -100,7 +101,7 @@ public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory
                     .detail(Details.USERNAME, username)
                     .user(user)
                     .error(Errors.EMAIL_SEND_FAILED);
-            logger.failedToSendPwdResetEmail(e);
+            ServicesLogger.LOGGER.failedToSendPwdResetEmail(e);
             Response challenge = context.form()
                     .setError(Messages.EMAIL_SENT_ERROR)
                     .createErrorPage();
                diff --git a/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java
index 4d3ae65..0cac336 100755
--- a/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/ClientAuthenticationFlow.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication;
 
+import org.jboss.logging.Logger;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.models.AuthenticationExecutionModel;
@@ -35,7 +36,7 @@ import java.util.List;
  */
 public class ClientAuthenticationFlow implements AuthenticationFlow {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ClientAuthenticationFlow.class);
 
     Response alternativeChallenge = null;
     AuthenticationProcessor processor;
@@ -73,7 +74,7 @@ public class ClientAuthenticationFlow implements AuthenticationFlow {
                 // Fallback to secret just in case (for backwards compatibility)
                 if (expectedClientAuthType == null) {
                     expectedClientAuthType = KeycloakModelUtils.getDefaultClientAuthenticatorType();
-                    logger.authMethodFallback(client.getClientId(), expectedClientAuthType);
+                    ServicesLogger.LOGGER.authMethodFallback(client.getClientId(), expectedClientAuthType);
                 }
 
                 // Check if client authentication matches
@@ -154,7 +155,7 @@ public class ClientAuthenticationFlow implements AuthenticationFlow {
         } else if (status == FlowStatus.FAILURE_CHALLENGE) {
             return sendChallenge(result, execution);
         } else {
-            logger.unknownResultStatus();
+            ServicesLogger.LOGGER.unknownResultStatus();
             throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR);
         }
     }
                diff --git a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
index f406c48..d099277 100755
--- a/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
+++ b/services/src/main/java/org/keycloak/authentication/DefaultAuthenticationFlow.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.models.AuthenticationFlowModel;
 import org.keycloak.models.ClientSessionModel;
@@ -32,7 +33,7 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public class DefaultAuthenticationFlow implements AuthenticationFlow {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(DefaultAuthenticationFlow.class);
     Response alternativeChallenge = null;
     AuthenticationExecutionModel challengedAlternativeExecution = null;
     boolean alternativeSuccessful = false;
@@ -247,7 +248,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
                 return processor.authenticate();
             default:
                 logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator());
-                logger.unknownResultStatus();
+                ServicesLogger.LOGGER.unknownResultStatus();
                 throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR);
         }
     }
                diff --git a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
index 26571e6..28747e0 100755
--- a/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
+++ b/services/src/main/java/org/keycloak/authentication/forms/RegistrationRecaptcha.java
@@ -23,6 +23,7 @@ import org.apache.http.client.HttpClient;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.message.BasicNameValuePair;
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.FormAction;
 import org.keycloak.authentication.FormActionFactory;
@@ -62,7 +63,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
     public static final String RECAPTCHA_REFERENCE_CATEGORY = "recaptcha";
     public static final String SITE_KEY = "site.key";
     public static final String SITE_SECRET = "secret";
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(RegistrationRecaptcha.class);
 
     public static final String PROVIDER_ID = "registration-recaptcha-action";
 
@@ -152,7 +153,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
                 content.close();
             }
         } catch (Exception e) {
-            logger.recaptchaFailed(e);
+            ServicesLogger.LOGGER.recaptchaFailed(e);
         }
         return success;
     }
                diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
index cafcd72..a2c43f7 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdatePassword.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.requiredactions;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.RequiredActionContext;
 import org.keycloak.authentication.RequiredActionFactory;
@@ -35,7 +36,6 @@ import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.ModelException;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.validation.Validation;
 
@@ -48,7 +48,7 @@ import java.util.concurrent.TimeUnit;
  * @version $Revision: 1 $
  */
 public class UpdatePassword implements RequiredActionProvider, RequiredActionFactory {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UpdatePassword.class);
     @Override
     public void evaluateTriggers(RequiredActionContext context) {
         int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();
                diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java
index 24b2547..fcc5df7 100644
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateProfile.java
@@ -29,7 +29,6 @@ import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.FormMessage;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.AttributeFormDataProcessor;
 import org.keycloak.services.validation.Validation;
@@ -43,7 +42,6 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
     @Override
     public void evaluateTriggers(RequiredActionContext context) {
     }
                diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
index 62344bd..829c705 100644
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/UpdateTotp.java
@@ -28,7 +28,6 @@ import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.CredentialValidation;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.validation.Validation;
 
@@ -40,7 +39,6 @@ import javax.ws.rs.core.Response;
  * @version $Revision: 1 $
  */
 public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
     @Override
     public void evaluateTriggers(RequiredActionContext context) {
     }
                diff --git a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
index 0888113..2d683d3 100755
--- a/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
+++ b/services/src/main/java/org/keycloak/authentication/requiredactions/VerifyEmail.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.authentication.requiredactions;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.authentication.RequiredActionContext;
 import org.keycloak.authentication.RequiredActionFactory;
@@ -41,7 +42,7 @@ import javax.ws.rs.core.Response;
  * @version $Revision: 1 $
  */
 public class VerifyEmail implements RequiredActionProvider, RequiredActionFactory {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(VerifyEmail.class);
     @Override
     public void evaluateTriggers(RequiredActionContext context) {
         if (context.getRealm().isVerifyEmail() && !context.getUser().isEmailVerified()) {
                diff --git a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
index fcb41a4..346cf82 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
@@ -17,21 +17,13 @@
 package org.keycloak.broker.oidc;
 
 import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
-import org.keycloak.jose.jwk.JSONWebKeySet;
-import org.keycloak.jose.jwk.JWK;
-import org.keycloak.jose.jwk.JWKParser;
 import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
-import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
-import org.keycloak.services.ServicesLogger;
-import org.keycloak.util.JWKSUtils;
 import org.keycloak.util.JsonSerialization;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.security.PublicKey;
 import java.util.Map;
 
 /**
@@ -39,8 +31,6 @@ import java.util.Map;
  */
 public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory<OIDCIdentityProvider> {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     public static final String PROVIDER_ID = "oidc";
 
     @Override
                diff --git a/services/src/main/java/org/keycloak/email/DefaultEmailSenderProvider.java b/services/src/main/java/org/keycloak/email/DefaultEmailSenderProvider.java
index f94fe07..235f123 100644
--- a/services/src/main/java/org/keycloak/email/DefaultEmailSenderProvider.java
+++ b/services/src/main/java/org/keycloak/email/DefaultEmailSenderProvider.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.email;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
@@ -44,7 +45,7 @@ import java.util.Properties;
  */
 public class DefaultEmailSenderProvider implements EmailSenderProvider {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(DefaultEmailSenderProvider.class);
 
     private final KeycloakSession session;
 
@@ -123,7 +124,7 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
             }
             transport.sendMessage(msg, new InternetAddress[]{new InternetAddress(address)});
         } catch (Exception e) {
-            logger.failedToSendEmail(e);
+            ServicesLogger.LOGGER.failedToSendEmail(e);
             throw new EmailException(e);
         } finally {
             if (transport != null) {
                diff --git a/services/src/main/java/org/keycloak/exportimport/ExportImportManager.java b/services/src/main/java/org/keycloak/exportimport/ExportImportManager.java
index b51513c..3e2188e 100644
--- a/services/src/main/java/org/keycloak/exportimport/ExportImportManager.java
+++ b/services/src/main/java/org/keycloak/exportimport/ExportImportManager.java
@@ -18,6 +18,7 @@
 package org.keycloak.exportimport;
 
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.services.ServicesLogger;
@@ -29,7 +30,7 @@ import java.io.IOException;
  */
 public class ExportImportManager {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ExportImportManager.class);
 
     private KeycloakSessionFactory sessionFactory;
 
@@ -82,13 +83,13 @@ public class ExportImportManager {
         try {
             Strategy strategy = ExportImportConfig.getStrategy();
             if (realmName == null) {
-                logger.fullModelImport(strategy.toString());
+                ServicesLogger.LOGGER.fullModelImport(strategy.toString());
                 importProvider.importModel(sessionFactory, strategy);
             } else {
-                logger.realmImportRequested(realmName, strategy.toString());
+                ServicesLogger.LOGGER.realmImportRequested(realmName, strategy.toString());
                 importProvider.importRealm(sessionFactory, realmName, strategy);
             }
-            logger.importSuccess();
+            ServicesLogger.LOGGER.importSuccess();
         } catch (IOException e) {
             throw new RuntimeException("Failed to run import", e);
         }
@@ -97,13 +98,13 @@ public class ExportImportManager {
     public void runExport() {
         try {
             if (realmName == null) {
-                logger.fullModelExportRequested();
+                ServicesLogger.LOGGER.fullModelExportRequested();
                 exportProvider.exportModel(sessionFactory);
             } else {
-                logger.realmExportRequested(realmName);
+                ServicesLogger.LOGGER.realmExportRequested(realmName);
                 exportProvider.exportRealm(sessionFactory, realmName);
             }
-            logger.exportSuccess();
+            ServicesLogger.LOGGER.exportSuccess();
         } catch (IOException e) {
             throw new RuntimeException("Failed to run export");
         }
                diff --git a/services/src/main/java/org/keycloak/keys/JavaKeystoreKeyProviderFactory.java b/services/src/main/java/org/keycloak/keys/JavaKeystoreKeyProviderFactory.java
index 0691607..518d321 100644
--- a/services/src/main/java/org/keycloak/keys/JavaKeystoreKeyProviderFactory.java
+++ b/services/src/main/java/org/keycloak/keys/JavaKeystoreKeyProviderFactory.java
@@ -43,10 +43,10 @@ public class JavaKeystoreKeyProviderFactory extends AbstractRsaKeyProviderFactor
     public static ProviderConfigProperty KEYSTORE_PASSWORD_PROPERTY = new ProviderConfigProperty(KEYSTORE_PASSWORD_KEY, "Keystore Password", "Password for the keys", STRING_TYPE, null, true);
 
     public static String KEY_ALIAS_KEY = "keyAlias";
-    public static ProviderConfigProperty KEY_ALIAS_PROPERTY = new ProviderConfigProperty(KEY_ALIAS_KEY, "Private Key Alias", "Alias for the private key", STRING_TYPE, null);
+    public static ProviderConfigProperty KEY_ALIAS_PROPERTY = new ProviderConfigProperty(KEY_ALIAS_KEY, "Key Alias", "Alias for the private key", STRING_TYPE, null);
 
     public static String KEY_PASSWORD_KEY = "keyPassword";
-    public static ProviderConfigProperty KEY_PASSWORD_PROPERTY = new ProviderConfigProperty(KEY_PASSWORD_KEY, "Private Key password", "Password for the private key", STRING_TYPE, null, true);
+    public static ProviderConfigProperty KEY_PASSWORD_PROPERTY = new ProviderConfigProperty(KEY_PASSWORD_KEY, "Key Password", "Password for the private key", STRING_TYPE, null, true);
 
     private static final String HELP_TEXT = "Loads keys from a Java keys file";
 
                diff --git a/services/src/main/java/org/keycloak/keys/loader/ClientPublicKeyLoader.java b/services/src/main/java/org/keycloak/keys/loader/ClientPublicKeyLoader.java
index 23eb726..d3f7fe5 100644
--- a/services/src/main/java/org/keycloak/keys/loader/ClientPublicKeyLoader.java
+++ b/services/src/main/java/org/keycloak/keys/loader/ClientPublicKeyLoader.java
@@ -22,6 +22,7 @@ import java.security.cert.X509Certificate;
 import java.util.Collections;
 import java.util.Map;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
 import org.keycloak.common.util.KeyUtils;
 import org.keycloak.jose.jwk.JSONWebKeySet;
@@ -44,7 +45,7 @@ import org.keycloak.util.JWKSUtils;
  */
 public class ClientPublicKeyLoader implements PublicKeyLoader {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ClientPublicKeyLoader.class);
 
     private final KeycloakSession session;
     private final ClientModel client;
                diff --git a/services/src/main/java/org/keycloak/keys/loader/OIDCIdentityProviderPublicKeyLoader.java b/services/src/main/java/org/keycloak/keys/loader/OIDCIdentityProviderPublicKeyLoader.java
index f41ded8..cf24a1b 100644
--- a/services/src/main/java/org/keycloak/keys/loader/OIDCIdentityProviderPublicKeyLoader.java
+++ b/services/src/main/java/org/keycloak/keys/loader/OIDCIdentityProviderPublicKeyLoader.java
@@ -17,10 +17,7 @@
 
 package org.keycloak.keys.loader;
 
-import java.security.PublicKey;
-import java.util.Collections;
-import java.util.Map;
-
+import org.jboss.logging.Logger;
 import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
 import org.keycloak.common.util.KeyUtils;
 import org.keycloak.common.util.PemUtils;
@@ -29,15 +26,18 @@ import org.keycloak.jose.jwk.JWK;
 import org.keycloak.keys.PublicKeyLoader;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.util.JWKSUtils;
 
+import java.security.PublicKey;
+import java.util.Collections;
+import java.util.Map;
+
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
  */
 public class OIDCIdentityProviderPublicKeyLoader implements PublicKeyLoader {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(OIDCIdentityProviderPublicKeyLoader.class);
 
     private final KeycloakSession session;
     private final OIDCIdentityProviderConfig config;
                diff --git a/services/src/main/java/org/keycloak/partialimport/AbstractPartialImport.java b/services/src/main/java/org/keycloak/partialimport/AbstractPartialImport.java
index cd81c56..ec42600 100644
--- a/services/src/main/java/org/keycloak/partialimport/AbstractPartialImport.java
+++ b/services/src/main/java/org/keycloak/partialimport/AbstractPartialImport.java
@@ -34,7 +34,6 @@ import java.util.Set;
  * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
  */
 public abstract class AbstractPartialImport<T> implements PartialImport<T> {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
     protected final Set<T> toOverwrite = new HashSet<>();
     protected final Set<T> toSkip = new HashSet<>();
@@ -100,7 +99,7 @@ public abstract class AbstractPartialImport<T> implements PartialImport<T> {
             try {
                 create(realm, session, resourceRep);
             } catch (Exception e) {
-                logger.overwriteError(e, getName(resourceRep));
+                ServicesLogger.LOGGER.overwriteError(e, getName(resourceRep));
                 throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
             }
 
@@ -122,7 +121,7 @@ public abstract class AbstractPartialImport<T> implements PartialImport<T> {
                 String modelId = getModelId(realm, session, resourceRep);
                 results.addResult(added(modelId, resourceRep));
             } catch (Exception e) {
-                logger.creationError(e, getName(resourceRep));
+                ServicesLogger.LOGGER.creationError(e, getName(resourceRep));
                 throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
             }
         }
                diff --git a/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java b/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
index 6fca177..c4b295b 100644
--- a/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
+++ b/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
@@ -45,7 +45,6 @@ import java.util.Set;
  * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
  */
 public class RolesPartialImport implements PartialImport<RolesRepresentation> {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
     private Set<RoleRepresentation> realmRolesToOverwrite;
     private Set<RoleRepresentation> realmRolesToSkip;
@@ -98,7 +97,7 @@ public class RolesPartialImport implements PartialImport<RolesRepresentation> {
         try {
             RepresentationToModel.importRoles(rep.getRoles(), realm);
         } catch (Exception e) {
-            logger.roleImportError(e);
+            ServicesLogger.LOGGER.roleImportError(e);
             throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
         }
 
                diff --git a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
index c1a101c..0c1462c 100755
--- a/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
+++ b/services/src/main/java/org/keycloak/protocol/AuthorizationEndpointBase.java
@@ -43,8 +43,6 @@ import javax.ws.rs.core.UriInfo;
  */
 public abstract class AuthorizationEndpointBase {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     protected RealmModel realm;
     protected EventBuilder event;
     protected AuthenticationManager authManager;
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 4ef0c5c..b979063 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.protocol.oidc.endpoints;
 
+import org.jboss.logging.Logger;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.authentication.AuthenticationProcessor;
@@ -54,7 +55,7 @@ import javax.ws.rs.core.Response;
  */
 public class AuthorizationEndpoint extends AuthorizationEndpointBase {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(AuthorizationEndpoint.class);
 
     public static final String CODE_AUTH_TYPE = "code";
 
@@ -104,7 +105,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         }
 
         if (!TokenUtil.isOIDCRequest(request.getScope())) {
-            logger.oidcScopeMissing();
+            ServicesLogger.LOGGER.oidcScopeMissing();
         }
 
         errorResponse = checkOIDCParams();
@@ -194,7 +195,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         String responseType = request.getResponseType();
 
         if (responseType == null) {
-            logger.missingParameter(OAuth2Constants.RESPONSE_TYPE);
+            ServicesLogger.LOGGER.missingParameter(OAuth2Constants.RESPONSE_TYPE);
             event.error(Errors.INVALID_REQUEST);
             return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Missing parameter: response_type");
         }
@@ -216,7 +217,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         try {
             parsedResponseMode = OIDCResponseMode.parse(request.getResponseMode(), parsedResponseType);
         } catch (IllegalArgumentException iae) {
-            logger.invalidParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
+            ServicesLogger.LOGGER.invalidParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
             event.error(Errors.INVALID_REQUEST);
             return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Invalid parameter: response_mode");
         }
@@ -225,19 +226,19 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
 
         // Disallowed by OIDC specs
         if (parsedResponseType.isImplicitOrHybridFlow() && parsedResponseMode == OIDCResponseMode.QUERY) {
-            logger.responseModeQueryNotAllowed();
+            ServicesLogger.LOGGER.responseModeQueryNotAllowed();
             event.error(Errors.INVALID_REQUEST);
             return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Response_mode 'query' not allowed for implicit or hybrid flow");
         }
 
         if ((parsedResponseType.hasResponseType(OIDCResponseType.CODE) || parsedResponseType.hasResponseType(OIDCResponseType.NONE)) && !client.isStandardFlowEnabled()) {
-            logger.flowNotAllowed("Standard");
+            ServicesLogger.LOGGER.flowNotAllowed("Standard");
             event.error(Errors.NOT_ALLOWED);
             return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client.");
         }
 
         if (parsedResponseType.isImplicitOrHybridFlow() && !client.isImplicitFlowEnabled()) {
-            logger.flowNotAllowed("Implicit");
+            ServicesLogger.LOGGER.flowNotAllowed("Implicit");
             event.error(Errors.NOT_ALLOWED);
             return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.");
         }
@@ -249,7 +250,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
 
     private Response checkOIDCParams() {
         if (parsedResponseType.isImplicitOrHybridFlow() && request.getNonce() == null) {
-            logger.missingParameter(OIDCLoginProtocol.NONCE_PARAM);
+            ServicesLogger.LOGGER.missingParameter(OIDCLoginProtocol.NONCE_PARAM);
             event.error(Errors.INVALID_REQUEST);
             return redirectErrorToClient(parsedResponseMode, OAuthErrorException.INVALID_REQUEST, "Missing parameter: nonce");
         }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
index 44822c6..0c17664 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.protocol.oidc.endpoints;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.OAuth2Constants;
@@ -38,7 +39,6 @@ import org.keycloak.representations.IDToken;
 import org.keycloak.representations.RefreshToken;
 import org.keycloak.services.ErrorPage;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.messages.Messages;
 import org.keycloak.services.resources.Cors;
@@ -60,7 +60,7 @@ import javax.ws.rs.core.UriInfo;
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class LogoutEndpoint {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(LogoutEndpoint.class);
 
     @Context
     private KeycloakSession session;
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java
index 4469c0f..c4de313 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java
@@ -36,8 +36,6 @@ import java.io.InputStream;
  */
 public class AuthorizationEndpointRequestParserProcessor {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     public static AuthorizationEndpointRequest parseRequest(EventBuilder event, KeycloakSession session, ClientModel client, MultivaluedMap<String, String> requestParams) {
         try {
             AuthorizationEndpointRequest request = new AuthorizationEndpointRequest();
@@ -63,7 +61,7 @@ public class AuthorizationEndpointRequestParserProcessor {
             return request;
 
         } catch (Exception e) {
-            logger.invalidRequest(e);
+            ServicesLogger.LOGGER.invalidRequest(e);
             event.error(Errors.INVALID_REQUEST);
             throw new ErrorPageException(session, Messages.INVALID_REQUEST);
         }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java
index 82d2c95..ea1c35e 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java
@@ -17,9 +17,9 @@
 
 package org.keycloak.protocol.oidc.endpoints.request;
 
+import org.jboss.logging.Logger;
 import org.keycloak.constants.AdapterConstants;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
-import org.keycloak.services.ServicesLogger;
 
 import java.util.HashSet;
 import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.Set;
  */
 abstract class AuthzEndpointRequestParser {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(AuthzEndpointRequestParser.class);
 
     /**
      * Max number of additional req params copied into client session note to prevent DoS attacks
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index 9a7fe3e..0a4803c 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.protocol.oidc.endpoints;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.OAuth2Constants;
@@ -68,7 +69,7 @@ import java.util.Map;
  */
 public class TokenEndpoint {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(TokenEndpoint.class);
     private MultivaluedMap<String, String> formParams;
     private ClientModel client;
     private Map<String, String> clientAuthAttributes;
@@ -309,7 +310,7 @@ public class TokenEndpoint {
     private void updateClientSession(ClientSessionModel clientSession) {
 
         if(clientSession == null) {
-            logger.clientSessionNull();
+            ServicesLogger.LOGGER.clientSessionNull();
             return;
         }
 
@@ -327,16 +328,16 @@ public class TokenEndpoint {
 
     private void updateClientSessions(List<ClientSessionModel> clientSessions) {
         if(clientSessions == null) {
-            logger.clientSessionNull();
+            ServicesLogger.LOGGER.clientSessionNull();
             return;
         }
         for (ClientSessionModel clientSession : clientSessions) {
             if(clientSession == null) {
-                logger.clientSessionNull();
+                ServicesLogger.LOGGER.clientSessionNull();
                 continue;
             }
             if(clientSession.getClient() == null) {
-                logger.clientModelNull();
+                ServicesLogger.LOGGER.clientModelNull();
                 continue;
             }
             if(client.getId().equals(clientSession.getClient().getId())) {
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
index 7c5b3b9..efe9434 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractOIDCProtocolMapper.java
@@ -18,10 +18,15 @@
 package org.keycloak.protocol.oidc.mappers;
 
 import org.keycloak.Config;
+import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -54,4 +59,46 @@ public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
     public void postInit(KeycloakSessionFactory factory) {
 
     }
+
+    public AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                              UserSessionModel userSession, ClientSessionModel clientSession) {
+
+        if (!OIDCAttributeMapperHelper.includeInUserInfo(mappingModel)) {
+            return token;
+        }
+
+        setClaim(token, mappingModel, userSession);
+        return token;
+    }
+
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
+
+        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)){
+            return token;
+        }
+
+        setClaim(token, mappingModel, userSession);
+        return token;
+    }
+
+    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                    UserSessionModel userSession, ClientSessionModel clientSession) {
+
+        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)){
+            return token;
+        }
+
+        setClaim(token, mappingModel, userSession);
+        return token;
+    }
+
+    /**
+     * Intended to be overridden in {@link ProtocolMapper} implementations to add claims to an token.
+     * @param token
+     * @param mappingModel
+     * @param userSession
+     */
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
+    }
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java
index 3e639aa..de4d054 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java
@@ -35,33 +35,7 @@ import java.util.Set;
  *
  * @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a>
  */
-abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
-
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) {
-            return token;
-        }
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) {
-            return token;
-        }
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
-
-    protected abstract void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession);
+abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
 
     /**
      * Returns the role names extracted from the given {@code roleModels} while recursively traversing "Composite Roles".
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
index 4f5d9cf..674c9ff 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java
@@ -39,26 +39,12 @@ import java.util.Map;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
 
     private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
 
     static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
-        configProperties.add(property);
+        OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, AddressMapper.class);
     }
 
     public static final String PROVIDER_ID = "oidc-address-mapper";
@@ -118,21 +104,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
     }
 
     @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-        setClaim(token, userSession);
-        return token;
-    }
-
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, userSession);
-        return token;
-    }
-
-    protected void setClaim(IDToken token, UserSessionModel userSession) {
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         AddressClaimSet addressSet = new AddressClaimSet();
         addressSet.setStreetAddress(user.getFirstAttribute("street"));
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
index 107e163..1e4ad9d 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/FullNameMapper.java
@@ -38,26 +38,12 @@ import java.util.Map;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
 
     private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
 
     static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
-        configProperties.add(property);
+        OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, FullNameMapper.class);
 
     }
 
@@ -88,28 +74,13 @@ public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
         return "Maps the user's first and last name to the OpenID Connect 'name' claim. Format is <first> + ' ' + <last>";
     }
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-        setClaim(token, userSession);
-        return token;
-    }
-
-    protected void setClaim(IDToken token, UserSessionModel userSession) {
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
         UserModel user = userSession.getUser();
         String first = user.getFirstName() == null ? "" : user.getFirstName() + " ";
         String last = user.getLastName() == null ? "" : user.getLastName();
         token.getOtherClaims().put("name", first + last);
     }
 
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, userSession);
-        return token;
-    }
-
     public static ProtocolMapperModel create(String name,
                                                         boolean consentRequired, String consentText,
                                                         boolean accessToken, boolean idToken) {
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
index d1410c3..41dbb47 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/GroupMembershipMapper.java
@@ -40,21 +40,13 @@ import java.util.Map;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
 
     private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
 
     static {
-        ProviderConfigProperty property;
-        ProviderConfigProperty property1;
-        property1 = new ProviderConfigProperty();
-        property1.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
-        property1.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
-        property1.setType(ProviderConfigProperty.STRING_TYPE);
-        property1.setDefaultValue("groups");
-        property1.setHelpText(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_TOOLTIP);
-        configProperties.add(property1);
-        property1 = new ProviderConfigProperty();
+        OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
+        ProviderConfigProperty property1 = new ProviderConfigProperty();
         property1.setName("full.path");
         property1.setLabel("Full group path");
         property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
@@ -62,23 +54,7 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
         property1.setHelpText("Include full path to group i.e. /top/level1/level2, false will just specify the group name");
         configProperties.add(property1);
 
-        property1 = new ProviderConfigProperty();
-        property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
-        property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
-        property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property1.setDefaultValue("true");
-        property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
-        configProperties.add(property1);
-        property1 = new ProviderConfigProperty();
-        property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
-        property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
-        property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property1.setDefaultValue("true");
-        property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
-        configProperties.add(property1);
-
-
-
+        OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, GroupMembershipMapper.class);
     }
 
     public static final String PROVIDER_ID = "oidc-group-membership-mapper";
@@ -113,15 +89,14 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
     }
 
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-        buildMembership(token, mappingModel, userSession);
-        return token;
-    }
+    /**
+     * Adds the group membership information to the {@link IDToken#otherClaims}.
+     * @param token
+     * @param mappingModel
+     * @param userSession
+     */
+    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
 
-    public void buildMembership(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
         List<String> membership = new LinkedList<>();
         boolean fullPath = useFullPath(mappingModel);
         for (GroupModel group : userSession.getUser().getGroups()) {
@@ -136,13 +111,6 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
         token.getOtherClaims().put(protocolClaim, membership);
     }
 
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        buildMembership(token, mappingModel, userSession);
-        return token;
-    }
-
     public static ProtocolMapperModel create(String name,
                                       String tokenClaimName,
                                       boolean consentRequired, String consentText,
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
index f5015ba..4062824 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedClaim.java
@@ -37,53 +37,24 @@ import java.util.Map;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
 
     private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
 
     public static final String CLAIM_VALUE = "claim.value";
 
     static {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
-        property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
-        property.setType(ProviderConfigProperty.STRING_TYPE);
-        property.setHelpText("Claim name you want to hard code into the token.  This can be a fully qualified name like 'address.street'.  In this case, a nested json object will be created.");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
+        OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
+
+        ProviderConfigProperty property = new ProviderConfigProperty();
         property.setName(CLAIM_VALUE);
         property.setLabel("Claim value");
         property.setType(ProviderConfigProperty.STRING_TYPE);
         property.setHelpText("Value of the claim you want to hard code.  'true' and 'false can be used for boolean values.");
         configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
-        property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
-        List<String> types = new ArrayList(3);
-        types.add("String");
-        types.add("long");
-        types.add("int");
-        types.add("boolean");
-        property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
-        property.setHelpText("JSON type that should be used for the value of the claim.  long, int, boolean, and String are valid values.");
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
-        property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
-        configProperties.add(property);
 
+        OIDCAttributeMapperHelper.addJsonTypeConfig(configProperties);
+        OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, HardcodedClaim.class);
     }
 
     public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
@@ -113,28 +84,13 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
         return "Hardcode a claim into the token.";
     }
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
+
         String attributeValue = mappingModel.getConfig().get(CLAIM_VALUE);
         if (attributeValue == null) return;
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue);
     }
 
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     public static ProtocolMapperModel create(String name,
                                       String hardcodedName,
                                       String hardcodedValue, String claimType,
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
index 5529857..03ecb91 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/HardcodedRole.java
@@ -83,6 +83,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
     @Override
     public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
                                             UserSessionModel userSession, ClientSessionModel clientSession) {
+
         String role = mappingModel.getConfig().get(ROLE_CONFIG);
         String[] scopedRole = KeycloakModelUtils.parseRole(role);
         String appName = scopedRole[0];
@@ -97,6 +98,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
             }
             access.addRole(role);
         }
+
         return token;
     }
 
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
index 0c05aa1..99b2610 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java
@@ -18,6 +18,7 @@
 package org.keycloak.protocol.oidc.mappers;
 
 import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.protocol.ProtocolMapper;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
@@ -34,7 +35,6 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class OIDCAttributeMapperHelper {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
     public static final String TOKEN_CLAIM_NAME = "claim.name";
     public static final String TOKEN_CLAIM_NAME_LABEL = "tokenClaimName.label";
@@ -67,7 +67,7 @@ public class OIDCAttributeMapperHelper {
                 return result;
             } else {
                 if (valueAsList.size() > 1) {
-                    logger.multipleValuesForMapper(attributeValue.toString(), mappingModel.getName());
+                    ServicesLogger.LOGGER.multipleValuesForMapper(attributeValue.toString(), mappingModel.getName());
                 }
 
                 attributeValue = valueAsList.get(0);
@@ -124,7 +124,7 @@ public class OIDCAttributeMapperHelper {
                                                         boolean consentRequired, String consentText,
                                                         boolean accessToken, boolean idToken,
                                                         String mapperId) {
-        return createClaimMapper(name, userAttribute,tokenClaimName, claimType, consentRequired, consentText, accessToken, idToken, false, mapperId);
+        return createClaimMapper(name, userAttribute,tokenClaimName, claimType, consentRequired, consentText, accessToken, idToken, true, mapperId);
     }
 
     public static ProtocolMapperModel createClaimMapper(String name,
@@ -163,18 +163,34 @@ public class OIDCAttributeMapperHelper {
     }
 
     public static boolean includeInUserInfo(ProtocolMapperModel mappingModel){
-        return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_USERINFO));
+        String includeInUserInfo = mappingModel.getConfig().get(INCLUDE_IN_USERINFO);
+
+        // Backwards compatibility
+        if (includeInUserInfo == null && includeInIDToken(mappingModel)) {
+            return true;
+        }
+
+        return "true".equals(includeInUserInfo);
     }
 
-    public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) {
-        ProviderConfigProperty property;
-        property = new ProviderConfigProperty();
+    public static void addAttributeConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
+        addTokenClaimNameConfig(configProperties);
+        addJsonTypeConfig(configProperties);
+
+        addIncludeInTokensConfig(configProperties, protocolMapperClass);
+    }
+
+    public static void addTokenClaimNameConfig(List<ProviderConfigProperty> configProperties) {
+        ProviderConfigProperty property = new ProviderConfigProperty();
         property.setName(TOKEN_CLAIM_NAME);
         property.setLabel(TOKEN_CLAIM_NAME_LABEL);
         property.setType(ProviderConfigProperty.STRING_TYPE);
         property.setHelpText(TOKEN_CLAIM_NAME_TOOLTIP);
         configProperties.add(property);
-        property = new ProviderConfigProperty();
+    }
+
+    public static void addJsonTypeConfig(List<ProviderConfigProperty> configProperties) {
+        ProviderConfigProperty property = new ProviderConfigProperty();
         property.setName(JSON_TYPE);
         property.setLabel(JSON_TYPE);
         List<String> types = new ArrayList(3);
@@ -183,29 +199,40 @@ public class OIDCAttributeMapperHelper {
         types.add("int");
         types.add("boolean");
         property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
+        property.setOptions(types);
         property.setHelpText(JSON_TYPE_TOOLTIP);
         configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(INCLUDE_IN_ID_TOKEN);
-        property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(INCLUDE_IN_ACCESS_TOKEN);
-        property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("true");
-        property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
-        configProperties.add(property);
-        property = new ProviderConfigProperty();
-        property.setName(INCLUDE_IN_USERINFO);
-        property.setLabel(INCLUDE_IN_USERINFO_LABEL);
-        property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
-        property.setDefaultValue("false");
-        property.setHelpText(INCLUDE_IN_USERINFO_HELP_TEXT);
-        configProperties.add(property);
+    }
+
+    public static void addIncludeInTokensConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
+        if (OIDCIDTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
+            ProviderConfigProperty property = new ProviderConfigProperty();
+            property.setName(INCLUDE_IN_ID_TOKEN);
+            property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
+            property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
+            property.setDefaultValue("true");
+            property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
+            configProperties.add(property);
+        }
+
+        if (OIDCAccessTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
+            ProviderConfigProperty property = new ProviderConfigProperty();
+            property.setName(INCLUDE_IN_ACCESS_TOKEN);
+            property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
+            property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
+            property.setDefaultValue("true");
+            property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
+            configProperties.add(property);
+        }
+
+        if (UserInfoTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
+            ProviderConfigProperty property = new ProviderConfigProperty();
+            property.setName(INCLUDE_IN_USERINFO);
+            property.setLabel(INCLUDE_IN_USERINFO_LABEL);
+            property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
+            property.setDefaultValue("true");
+            property.setHelpText(INCLUDE_IN_USERINFO_HELP_TEXT);
+            configProperties.add(property);
+        }
     }
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java
index 0f6138a..d0d1398 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/PairwiseSubMapperHelper.java
@@ -3,10 +3,8 @@ package org.keycloak.protocol.oidc.mappers;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 public class PairwiseSubMapperHelper {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
     public static final String SECTOR_IDENTIFIER_URI = "sectorIdentifierUri";
     public static final String SECTOR_IDENTIFIER_URI_LABEL = "sectorIdentifierUri.label";
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
index 5f54c07..fcdc373 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/RoleNameMapper.java
@@ -25,6 +25,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -88,8 +89,8 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
     }
 
     @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session2,
-                                            UserSessionModel userSession2, ClientSessionModel clientSessio2n) {
+    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
+                                            UserSessionModel userSession, ClientSessionModel clientSession) {
         String role = mappingModel.getConfig().get(ROLE_CONFIG);
         String newName = mappingModel.getConfig().get(NEW_ROLE_NAME);
 
@@ -120,6 +121,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
         } else {
             access = token.addAccess(newAppName);
         }
+
         access.addRole(newRoleName);
         return token;
     }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA256PairwiseSubMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA256PairwiseSubMapper.java
index fdb1e94..28a0b87 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA256PairwiseSubMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/SHA256PairwiseSubMapper.java
@@ -1,5 +1,6 @@
 package org.keycloak.protocol.oidc.mappers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperContainerModel;
 import org.keycloak.models.ProtocolMapperModel;
@@ -9,7 +10,6 @@ import org.keycloak.protocol.ProtocolMapperConfigException;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 import java.nio.charset.Charset;
 import java.security.MessageDigest;
@@ -23,7 +23,7 @@ import java.util.UUID;
 public class SHA256PairwiseSubMapper extends AbstractPairwiseSubMapper {
     public static final String PROVIDER_ID = "sha256";
     private static final String HASH_ALGORITHM = "SHA-256";
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(SHA256PairwiseSubMapper.class);
     private final Charset charset;
 
     public SHA256PairwiseSubMapper() {
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
index 56e7a48..e6d0d20 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
@@ -51,7 +51,7 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
         property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
         property.setType(ProviderConfigProperty.STRING_TYPE);
         configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserAttributeMapper.class);
 
         property = new ProviderConfigProperty();
         property.setName(ProtocolMapperUtils.MULTIVALUED);
@@ -89,16 +89,8 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
         return "Map a custom user attribute to a token claim.";
     }
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
+
         UserModel user = userSession.getUser();
         String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
         List<String> attributeValue = KeycloakModelUtils.resolveAttribute(user, attributeName);
@@ -106,24 +98,6 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue);
     }
 
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
-    @Override
-    public AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-
-        if (!OIDCAttributeMapperHelper.includeInUserInfo(mappingModel)) {
-            return token;
-        }
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     public static ProtocolMapperModel createClaimMapper(String name,
                                                         String userAttribute,
                                                         String tokenClaimName, String claimType,
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java
index dcb55a8..01d47e1 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java
@@ -47,7 +47,7 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
         clientId.setName(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID);
         clientId.setLabel(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_LABEL);
         clientId.setHelpText(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID_HELP_TEXT);
-        clientId.setType(ProviderConfigProperty.STRING_TYPE);
+        clientId.setType(ProviderConfigProperty.CLIENT_LIST_TYPE);
         CONFIG_PROPERTIES.add(clientId);
 
         ProviderConfigProperty clientRolePrefix = new ProviderConfigProperty();
@@ -57,7 +57,7 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
         clientRolePrefix.setType(ProviderConfigProperty.STRING_TYPE);
         CONFIG_PROPERTIES.add(clientRolePrefix);
 
-        OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES);
+        OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES, UserClientRoleMappingMapper.class);
     }
 
     public List<ProviderConfigProperty> getConfigProperties() {
@@ -100,4 +100,21 @@ public class UserClientRoleMappingMapper extends AbstractUserRoleMappingMapper {
             OIDCAttributeMapperHelper.mapClaim(token, mappingModel, clientRoleNames);
         }
     }
+
+
+    public static ProtocolMapperModel create(String clientId, String clientRolePrefix,
+                                             String name,
+                                             String tokenClaimName,
+                                             boolean accessToken, boolean idToken) {
+        ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, "foo",
+                tokenClaimName, "String",
+                true, name,
+                accessToken, idToken,
+                PROVIDER_ID);
+
+        mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_CLIENT_ID, clientId);
+        mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_CLIENT_ROLE_MAPPING_ROLE_PREFIX, clientRolePrefix);
+        return mapper;
+
+    }
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
index a93e62b..67ac1a2 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserInfoTokenMapper.java
@@ -29,5 +29,5 @@ import org.keycloak.representations.AccessToken;
 public interface UserInfoTokenMapper {
 
     AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                     UserSessionModel userSession, ClientSessionModel clientSession);
+                                               UserSessionModel userSession, ClientSessionModel clientSession);
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
index e0ea4c3..6fd6491 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserPropertyMapper.java
@@ -38,7 +38,7 @@ import java.util.List;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
+public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
     private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
 
     static {
@@ -49,7 +49,7 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
         property.setType(ProviderConfigProperty.STRING_TYPE);
         property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
         configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserPropertyMapper.class);
     }
 
     public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
@@ -79,24 +79,8 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
         return "Map a built in user property (email, firstName, lastName) to a token claim.";
     }
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-        setClaim(token, mappingModel, userSession);
-
-        return token;
-    }
-
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, mappingModel, userSession);
-
-        return token;
-    }
-
     protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
+
         UserModel user = userSession.getUser();
         String propertyName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
         String propertyValue = ProtocolMapperUtils.getUserModelValue(user, propertyName);
@@ -114,6 +98,4 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
                 accessToken, idToken,
                 PROVIDER_ID);
     }
-
-
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserRealmRoleMappingMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserRealmRoleMappingMapper.java
index 3346070..ef98182 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserRealmRoleMappingMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserRealmRoleMappingMapper.java
@@ -21,11 +21,14 @@ import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.IDToken;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -48,7 +51,7 @@ public class UserRealmRoleMappingMapper extends AbstractUserRoleMappingMapper {
         realmRolePrefix.setType(ProviderConfigProperty.STRING_TYPE);
         CONFIG_PROPERTIES.add(realmRolePrefix);
 
-        OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES);
+        OIDCAttributeMapperHelper.addAttributeConfig(CONFIG_PROPERTIES, UserRealmRoleMappingMapper.class);
     }
 
     public List<ProviderConfigProperty> getConfigProperties() {
@@ -80,8 +83,23 @@ public class UserRealmRoleMappingMapper extends AbstractUserRoleMappingMapper {
         UserModel user = userSession.getUser();
 
         String rolePrefix = mappingModel.getConfig().get(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX);
-        Set<String> realmRoleNames = flattenRoleModelToRoleNames(user.getRoleMappings(), rolePrefix);
+        Set<String> realmRoleNames = flattenRoleModelToRoleNames(user.getRealmRoleMappings(), rolePrefix);
 
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, realmRoleNames);
     }
+
+
+    public static ProtocolMapperModel create(String realmRolePrefix,
+                                             String name,
+                                             String tokenClaimName, boolean accessToken, boolean idToken) {
+        ProtocolMapperModel mapper = OIDCAttributeMapperHelper.createClaimMapper(name, "foo",
+                tokenClaimName, "String",
+                true, name,
+                accessToken, idToken,
+                PROVIDER_ID);
+
+        mapper.getConfig().put(ProtocolMapperUtils.USER_MODEL_REALM_ROLE_MAPPING_ROLE_PREFIX, realmRolePrefix);
+        return mapper;
+
+    }
 }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
index 0016103..fd6bfe1 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserSessionNoteMapper.java
@@ -49,7 +49,7 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements
         property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
         property.setType(ProviderConfigProperty.STRING_TYPE);
         configProperties.add(property);
-        OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
+        OIDCAttributeMapperHelper.addAttributeConfig(configProperties, UserSessionNoteMapper.class);
     }
 
     public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";
@@ -79,29 +79,14 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements
         return "Map a custom user session note to a token claim.";
     }
 
-    @Override
-    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
-                                            UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
-
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
+
         String noteName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_SESSION_NOTE);
         String noteValue = userSession.getNote(noteName);
         if (noteValue == null) return;
         OIDCAttributeMapperHelper.mapClaim(token, mappingModel, noteValue);
     }
 
-    @Override
-    public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
-        if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
-        setClaim(token, mappingModel, userSession);
-        return token;
-    }
-
     public static ProtocolMapperModel createClaimMapper(String name,
                                                         String userSessionNote,
                                                         String tokenClaimName, String jsonType,
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index c263405..7e41411 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.protocol.oidc;
 
+import org.jboss.logging.Logger;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.common.util.Time;
@@ -84,7 +85,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
     public static final String CLIENT_SECRET_JWT = "client_secret_jwt";
     public static final String PRIVATE_KEY_JWT = "private_key_jwt";
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(OIDCLoginProtocol.class);
 
     protected KeycloakSession session;
 
@@ -233,7 +234,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
             case PASSIVE_LOGIN_REQUIRED:
                 return OAuthErrorException.LOGIN_REQUIRED;
             default:
-                logger.untranslatedProtocol(error.name());
+                ServicesLogger.LOGGER.untranslatedProtocol(error.name());
                 return OAuthErrorException.SERVER_ERROR;
         }
     }
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
index d830fcd..03328a0 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.protocol.oidc;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.constants.KerberosConstants;
 import org.keycloak.common.util.UriUtils;
 import org.keycloak.events.EventBuilder;
@@ -48,7 +49,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
-    private static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(OIDCLoginProtocolFactory.class);
 
     public static final String USERNAME = "username";
     public static final String EMAIL = "email";
@@ -193,7 +194,7 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
 
         // Backwards compatibility only
         if (rep.isDirectGrantsOnly() != null) {
-            logger.usingDeprecatedDirectGrantsOnly();
+            ServicesLogger.LOGGER.usingDeprecatedDirectGrantsOnly();
             newClient.setStandardFlowEnabled(!rep.isDirectGrantsOnly());
             newClient.setDirectAccessGrantsEnabled(rep.isDirectGrantsOnly());
         } else {
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
index a07ea70..2c983ed 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolService.java
@@ -20,9 +20,10 @@ package org.keycloak.protocol.oidc;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.EventBuilder;
+import org.keycloak.forms.login.LoginFormsProvider;
+import org.keycloak.jose.jwk.JSONWebKeySet;
 import org.keycloak.jose.jwk.JWK;
 import org.keycloak.jose.jwk.JWKBuilder;
-import org.keycloak.forms.login.LoginFormsProvider;
 import org.keycloak.keys.KeyMetadata;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
@@ -31,8 +32,6 @@ import org.keycloak.protocol.oidc.endpoints.LoginStatusIframeEndpoint;
 import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint;
 import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
 import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint;
-import org.keycloak.jose.jwk.JSONWebKeySet;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.resources.RealmsResource;
 
 import javax.ws.rs.GET;
@@ -55,8 +54,6 @@ import java.util.List;
  */
 public class OIDCLoginProtocolService {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
-
     private RealmModel realm;
     private TokenManager tokenManager;
     private EventBuilder event;
                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 308c771..c671607 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -506,10 +506,11 @@ public class TokenManager {
         for (ProtocolMapperModel mapping : mappings) {
 
             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);
-
+            if (mapper instanceof OIDCAccessTokenMapper) {
+                token = ((OIDCAccessTokenMapper) mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
+            }
         }
+
         return token;
     }
 
@@ -520,16 +521,11 @@ public class TokenManager {
         for (ProtocolMapperModel mapping : mappings) {
 
             ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
-            if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue;
-
-            if(mapper instanceof UserInfoTokenMapper){
-                token = ((UserInfoTokenMapper)mapper).transformUserInfoToken(token, mapping, session, userSession, clientSession);
-                continue;
+            if (mapper instanceof UserInfoTokenMapper) {
+                token = ((UserInfoTokenMapper) mapper).transformUserInfoToken(token, mapping, session, userSession, clientSession);
             }
-
-            token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
-
         }
+
         return token;
     }
 
@@ -540,13 +536,12 @@ public class TokenManager {
         for (ProtocolMapperModel mapping : mappings) {
 
             ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
-            if (mapper == null || !(mapper instanceof OIDCIDTokenMapper)) continue;
-            token = ((OIDCIDTokenMapper)mapper).transformIDToken(token, mapping, session, userSession, clientSession);
-
+            if (mapper instanceof OIDCIDTokenMapper) {
+                token = ((OIDCIDTokenMapper) mapper).transformIDToken(token, mapping, session, userSession, clientSession);
+            }
         }
     }
 
-
     protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession, UriInfo uriInfo) {
         AccessToken token = new AccessToken();
         if (clientSession != null) token.clientSession(clientSession.getId());
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java
index 7535e65..75a86c8 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/PairwiseSubMapperUtils.java
@@ -1,9 +1,9 @@
 package org.keycloak.protocol.oidc.utils;
 
+import org.jboss.logging.Logger;
 import org.keycloak.protocol.oidc.mappers.AbstractPairwiseSubMapper;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -16,7 +16,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 public class PairwiseSubMapperUtils {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(PairwiseSubMapperUtils.class);
 
     /**
      * Returns a set of valid redirect URIs from the root url and redirect URIs registered on a client.
                diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index 125769e..03bc9e6 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -17,10 +17,10 @@
 
 package org.keycloak.protocol.oidc.utils;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.Constants;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.Urls;
 
 import javax.ws.rs.core.UriInfo;
@@ -33,7 +33,7 @@ import java.util.Set;
  */
 public class RedirectUtils {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(RedirectUtils.class);
 
     public static String verifyRealmRedirectUri(UriInfo uriInfo, String redirectUri, RealmModel realm) {
         Set<String> validRedirects = getValidateRedirectUris(uriInfo, realm);
                diff --git a/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java b/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
index cc7c324..b333afa 100644
--- a/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
+++ b/services/src/main/java/org/keycloak/protocol/RestartLoginCookie.java
@@ -18,21 +18,19 @@
 package org.keycloak.protocol;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jboss.logging.Logger;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.HMACProvider;
 import org.keycloak.jose.jws.crypto.RSAProvider;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeyManager;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.util.CookieHelper;
 
-import javax.crypto.SecretKey;
 import javax.ws.rs.core.Cookie;
 import javax.ws.rs.core.UriInfo;
 import java.security.PublicKey;
@@ -47,7 +45,7 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class RestartLoginCookie {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(RestartLoginCookie.class);
     public static final String KC_RESTART = "KC_RESTART";
     @JsonProperty("cs")
     protected String clientSession;
                diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
index 59ddd49..c1cf9c4 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java
@@ -85,7 +85,7 @@ public class AttributeStatementHelper {
         types.add(AttributeStatementHelper.URI_REFERENCE);
         types.add(AttributeStatementHelper.UNSPECIFIED);
         property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
+        property.setOptions(types);
         configProperties.add(property);
 
     }
                diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
index 289c40e..1a2db26 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/GroupMembershipMapper.java
@@ -65,7 +65,7 @@ public class GroupMembershipMapper extends AbstractSAMLProtocolMapper implements
         types.add(AttributeStatementHelper.URI_REFERENCE);
         types.add(AttributeStatementHelper.UNSPECIFIED);
         property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
+        property.setOptions(types);
         configProperties.add(property);
         property = new ProviderConfigProperty();
         property.setName(SINGLE_GROUP_ATTRIBUTE);
                diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
index 82d26d3..dd27472 100755
--- a/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/RoleListMapper.java
@@ -69,7 +69,7 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
         types.add(AttributeStatementHelper.URI_REFERENCE);
         types.add(AttributeStatementHelper.UNSPECIFIED);
         property.setType(ProviderConfigProperty.LIST_TYPE);
-        property.setDefaultValue(types);
+        property.setOptions(types);
         configProperties.add(property);
         property = new ProviderConfigProperty();
         property.setName(SINGLE_ROLE_ATTRIBUTE);
                diff --git a/services/src/main/java/org/keycloak/provider/FileSystemProviderLoaderFactory.java b/services/src/main/java/org/keycloak/provider/FileSystemProviderLoaderFactory.java
index 2007d4b..414bea8 100644
--- a/services/src/main/java/org/keycloak/provider/FileSystemProviderLoaderFactory.java
+++ b/services/src/main/java/org/keycloak/provider/FileSystemProviderLoaderFactory.java
@@ -16,7 +16,7 @@
  */
 package org.keycloak.provider;
 
-import org.keycloak.services.ServicesLogger;
+import org.jboss.logging.Logger;
 
 import java.io.File;
 import java.io.FilenameFilter;
@@ -30,7 +30,7 @@ import java.util.List;
  */
 public class FileSystemProviderLoaderFactory implements ProviderLoaderFactory {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(FileSystemProviderLoaderFactory.class);
 
     @Override
     public boolean supports(String type) {
                diff --git a/services/src/main/java/org/keycloak/provider/ProviderManager.java b/services/src/main/java/org/keycloak/provider/ProviderManager.java
index e5d9712..9db3181 100644
--- a/services/src/main/java/org/keycloak/provider/ProviderManager.java
+++ b/services/src/main/java/org/keycloak/provider/ProviderManager.java
@@ -16,8 +16,8 @@
  */
 package org.keycloak.provider;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.services.ServicesLogger;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -32,7 +32,7 @@ import java.util.ServiceLoader;
  */
 public class ProviderManager {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ProviderManager.class);
 
     private List<ProviderLoader> loaders = new LinkedList<ProviderLoader>();
     private MultivaluedHashMap<Class<? extends Provider>, ProviderFactory> cache = new MultivaluedHashMap<>();
                diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
index 034ba9d..89f93f0 100755
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
@@ -16,8 +16,8 @@
  */
 package org.keycloak.services.clientregistration.oidc;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.util.Time;
-import org.keycloak.events.EventBuilder;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ProtocolMapperModel;
@@ -33,13 +33,8 @@ import org.keycloak.representations.oidc.OIDCClientRepresentation;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.clientregistration.AbstractClientRegistrationProvider;
-import org.keycloak.services.clientregistration.ClientRegistrationAuth;
-import org.keycloak.services.clientregistration.ClientRegistrationContext;
-import org.keycloak.services.clientregistration.DefaultClientRegistrationContext;
 import org.keycloak.services.clientregistration.ClientRegistrationException;
 import org.keycloak.services.clientregistration.ErrorCodes;
-import org.keycloak.services.validation.PairwiseClientValidator;
-import org.keycloak.services.validation.ValidationMessages;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -52,10 +47,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.net.URI;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
@@ -63,7 +56,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
  */
 public class OIDCClientRegistrationProvider extends AbstractClientRegistrationProvider {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(OIDCClientRegistrationProvider.class);
 
     public OIDCClientRegistrationProvider(KeycloakSession session) {
         super(session);
@@ -91,7 +84,7 @@ public class OIDCClientRegistrationProvider extends AbstractClientRegistrationPr
             clientOIDC.setClientIdIssuedAt(Time.currentTime());
             return Response.created(uri).entity(clientOIDC).build();
         } catch (ClientRegistrationException cre) {
-            logger.clientRegistrationException(cre.getMessage());
+            ServicesLogger.LOGGER.clientRegistrationException(cre.getMessage());
             throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client metadata invalid", Response.Status.BAD_REQUEST);
         }
     }
@@ -122,7 +115,7 @@ public class OIDCClientRegistrationProvider extends AbstractClientRegistrationPr
             clientOIDC = DescriptionConverter.toExternalResponse(session, client, uri);
             return Response.ok(clientOIDC).build();
         } catch (ClientRegistrationException cre) {
-            logger.clientRegistrationException(cre.getMessage());
+            ServicesLogger.LOGGER.clientRegistrationException(cre.getMessage());
             throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client metadata invalid", Response.Status.BAD_REQUEST);
         }
     }
                diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientTemplatesClientRegistrationPolicyFactory.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientTemplatesClientRegistrationPolicyFactory.java
index c886e8f..cc71424 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientTemplatesClientRegistrationPolicyFactory.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ClientTemplatesClientRegistrationPolicyFactory.java
@@ -60,7 +60,7 @@ public class ClientTemplatesClientRegistrationPolicyFactory extends AbstractClie
         property.setType(ProviderConfigProperty.MULTIVALUED_LIST_TYPE);
 
         if (session != null) {
-            property.setDefaultValue(getClientTemplates(session));
+            property.setOptions(getClientTemplates(session));
         }
 
         configProperties = Collections.singletonList(property);
                diff --git a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ProtocolMappersClientRegistrationPolicyFactory.java b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ProtocolMappersClientRegistrationPolicyFactory.java
index e794e3c..a9aea14 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ProtocolMappersClientRegistrationPolicyFactory.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/policy/impl/ProtocolMappersClientRegistrationPolicyFactory.java
@@ -58,7 +58,7 @@ public class ProtocolMappersClientRegistrationPolicyFactory extends AbstractClie
         property.setLabel("allowed-protocol-mappers.label");
         property.setHelpText("allowed-protocol-mappers.tooltip");
         property.setType(ProviderConfigProperty.MULTIVALUED_LIST_TYPE);
-        property.setDefaultValue(getProtocolMapperFactoryIds());
+        property.setOptions(getProtocolMapperFactoryIds());
         configProperties.add(property);
 
         property = new ProviderConfigProperty();
                diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index c26dced..7fbd7a3 100644
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -228,6 +228,11 @@ public class DefaultKeycloakSession implements KeycloakSession {
     }
 
     @Override
+    public Class<? extends Provider> getProviderClass(String providerClassName) {
+        return factory.getProviderClass(providerClassName);
+    }
+
+    @Override
     public RealmProvider realms() {
         if (model == null) {
             model = getRealmProvider();
                diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
index caf281a..bd28e20 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSessionFactory.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.common.util.MultivaluedHashMap;
 import org.keycloak.models.KeycloakSession;
@@ -40,7 +41,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
 
 public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, ProviderManagerDeployer {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(DefaultKeycloakSessionFactory.class);
 
     private Set<Spi> spis = new HashSet<>();
     private Map<Class<? extends Provider>, String> provider = new HashMap<>();
@@ -193,7 +194,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
                     factory.init(scope);
 
                     if (spi.isInternal() && !isInternal(factory)) {
-                        logger.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
+                        ServicesLogger.LOGGER.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
                     }
 
                     factories.put(factory.getId(), factory);
@@ -208,7 +209,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
                         factory.init(scope);
 
                         if (spi.isInternal() && !isInternal(factory)) {
-                            logger.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
+                            ServicesLogger.LOGGER.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
                         }
 
                         factories.put(factory.getId(), factory);
@@ -251,7 +252,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
                 factory.init(scope);
 
                 if (spi.isInternal() && !isInternal(factory)) {
-                    logger.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
+                    ServicesLogger.LOGGER.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
                 }
 
                 factories.put(factory.getId(), factory);
@@ -264,7 +265,7 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
                         factory.init(scope);
 
                         if (spi.isInternal() && !isInternal(factory)) {
-                            logger.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
+                            ServicesLogger.LOGGER.spiMayChange(factory.getId(), factory.getClass().getName(), spi.getName());
                         }
 
                         factories.put(factory.getId(), factory);
@@ -339,6 +340,15 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
         return ids;
     }
 
+    Class<? extends Provider> getProviderClass(String providerClassName) {
+        for (Class<? extends Provider> clazz : factoriesMap.keySet()) {
+            if (clazz.getName().equals(providerClassName)) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
     public void close() {
         ProviderManagerRegistry.SINGLETON.setDeployer(null);
         for (Map<String, ProviderFactory> factories : factoriesMap.values()) {
                diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakTransactionManager.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakTransactionManager.java
index 81379a1..0039fa0 100755
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakTransactionManager.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakTransactionManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakTransaction;
 import org.keycloak.models.KeycloakTransactionManager;
@@ -31,7 +32,7 @@ import java.util.List;
  */
 public class DefaultKeycloakTransactionManager implements KeycloakTransactionManager {
 
-    public static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(DefaultKeycloakTransactionManager.class);
 
     private List<KeycloakTransaction> prepare = new LinkedList<KeycloakTransaction>();
     private List<KeycloakTransaction> transactions = new LinkedList<KeycloakTransaction>();
@@ -140,7 +141,7 @@ public class DefaultKeycloakTransactionManager implements KeycloakTransactionMan
                 try {
                     tx.rollback();
                 } catch (RuntimeException e) {
-                    logger.exceptionDuringRollback(e);
+                    ServicesLogger.LOGGER.exceptionDuringRollback(e);
                 }
             }
         }
                diff --git a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
index 89cf129..7de8ee4 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplianceBootstrap.java
@@ -27,7 +27,6 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.utils.DefaultKeyProviders;
-import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.ServicesLogger;
 
@@ -37,7 +36,6 @@ import org.keycloak.services.ServicesLogger;
  */
 public class ApplianceBootstrap {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
     private final KeycloakSession session;
 
     public ApplianceBootstrap(KeycloakSession session) {
@@ -63,7 +61,7 @@ public class ApplianceBootstrap {
         }
 
         String adminRealmName = Config.getAdminRealm();
-        logger.initializingAdminRealm(adminRealmName);
+        ServicesLogger.LOGGER.initializingAdminRealm(adminRealmName);
 
         RealmManager manager = new RealmManager(session);
         manager.setContextPath(contextPath);
                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 4b33407..021011a 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -224,7 +224,7 @@ public class AuthenticationManager {
                     protocol.backchannelLogout(userSession, clientSession);
                     clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
                 } catch (Exception e) {
-                    ServicesLogger.ROOT_LOGGER.failedToLogoutClient(e);
+                    ServicesLogger.LOGGER.failedToLogoutClient(e);
                 }
             }
         }
@@ -245,7 +245,7 @@ public class AuthenticationManager {
                     return response;
                 }
             } catch (Exception e) {
-                ServicesLogger.ROOT_LOGGER.failedToLogoutClient(e);
+                ServicesLogger.LOGGER.failedToLogoutClient(e);
             }
 
         }
                diff --git a/services/src/main/java/org/keycloak/services/managers/ClientManager.java b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
index 707dc34..b648bbd 100644
--- a/services/src/main/java/org/keycloak/services/managers/ClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java
@@ -18,6 +18,7 @@ package org.keycloak.services.managers;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.ClientAuthenticator;
 import org.keycloak.authentication.ClientAuthenticatorFactory;
 import org.keycloak.common.constants.ServiceAccountConstants;
@@ -37,7 +38,6 @@ import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
 import org.keycloak.representations.adapters.config.BaseRealmConfig;
 import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 import java.net.URI;
 import java.util.Collections;
@@ -52,7 +52,7 @@ import java.util.TreeSet;
  * @version $Revision: 1 $
  */
 public class ClientManager {
-    protected ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ClientManager.class);
 
     protected RealmManager realmManager;
 
                diff --git a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
index 33c81c1..76c9cc7 100644
--- a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
@@ -17,6 +17,7 @@
 package org.keycloak.services.managers;
 
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.common.util.Time;
 import org.keycloak.models.KeycloakSession;
@@ -39,7 +40,7 @@ import java.util.concurrent.TimeUnit;
  * @version $Revision: 1 $
  */
 public class DefaultBruteForceProtector implements Runnable, BruteForceProtector {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(DefaultBruteForceProtector.class);
 
     protected volatile boolean run = true;
     protected int maxDeltaTimeSeconds = 60 * 60 * 12; // 12 hours
@@ -202,7 +203,7 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
                             session.close();
                         }
                     } catch (Exception e) {
-                        logger.failedProcessingType(e);
+                        ServicesLogger.LOGGER.failedProcessingType(e);
                     }
                 } catch (InterruptedException e) {
                     break;
@@ -214,7 +215,7 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
     }
 
     protected void logFailure(LoginEvent event) {
-        logger.loginFailure(event.userId, event.ip);
+        ServicesLogger.LOGGER.loginFailure(event.userId, event.ip);
         failures++;
         long delta = 0;
         if (lastFailure > 0) {
                diff --git a/services/src/main/java/org/keycloak/services/managers/LDAPConnectionTestManager.java b/services/src/main/java/org/keycloak/services/managers/LDAPConnectionTestManager.java
index b62d1d9..94eb6b7 100755
--- a/services/src/main/java/org/keycloak/services/managers/LDAPConnectionTestManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/LDAPConnectionTestManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.managers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.LDAPConstants;
 import org.keycloak.services.ServicesLogger;
 
@@ -29,14 +30,14 @@ import java.util.Hashtable;
  */
 public class LDAPConnectionTestManager {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(LDAPConnectionTestManager.class);
 
     public static final String TEST_CONNECTION = "testConnection";
     public static final String TEST_AUTHENTICATION = "testAuthentication";
 
     public boolean testLDAP(String action, String connectionUrl, String bindDn, String bindCredential, String useTruststoreSpi) {
         if (!TEST_CONNECTION.equals(action) && !TEST_AUTHENTICATION.equals(action)) {
-            logger.unknownAction(action);
+            ServicesLogger.LOGGER.unknownAction(action);
             return false;
         }
 
@@ -73,14 +74,14 @@ public class LDAPConnectionTestManager {
             return true;
         } catch (Exception ne) {
             String errorMessage = (TEST_AUTHENTICATION.equals(action)) ? "Error when authenticating to LDAP: " : "Error when connecting to LDAP: ";
-            logger.errorAuthenticating(ne, errorMessage + ne.getMessage());
+            ServicesLogger.LOGGER.errorAuthenticating(ne, errorMessage + ne.getMessage());
             return false;
         } finally {
             if (ldapContext != null) {
                 try {
                     ldapContext.close();
                 } catch (NamingException ne) {
-                    logger.errorClosingLDAP(ne);
+                    ServicesLogger.LOGGER.errorClosingLDAP(ne);
                 }
             }
         }
                diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
index 488df50..12e0449 100755
--- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.managers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.TokenIdGenerator;
 import org.keycloak.common.util.KeycloakUriBuilder;
 import org.keycloak.common.util.MultivaluedHashMap;
@@ -53,7 +54,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class ResourceAdminManager {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ResourceAdminManager.class);
     private static final String CLIENT_SESSION_HOST_PROPERTY = "${application.session.host}";
 
     private KeycloakSession session;
@@ -253,7 +254,7 @@ public class ResourceAdminManager {
             logger.debugf("logout success for %s: %s", managementUrl, success);
             return success;
         } catch (IOException e) {
-            logger.logoutFailed(e, resource.getClientId());
+            ServicesLogger.LOGGER.logoutFailed(e, resource.getClientId());
             return false;
         }
     }
@@ -304,7 +305,7 @@ public class ResourceAdminManager {
             logger.debugf("pushRevocation success for %s: %s", managementUrl, success);
             return success;
         } catch (IOException e) {
-            logger.failedToSendRevocation(e);
+            ServicesLogger.LOGGER.failedToSendRevocation(e);
             return false;
         }
     }
@@ -342,7 +343,7 @@ public class ResourceAdminManager {
             logger.debugf("testAvailability success for %s: %s", managementUrl, success);
             return success;
         } catch (IOException e) {
-            logger.availabilityTestFailed(managementUrl);
+            ServicesLogger.LOGGER.availabilityTestFailed(managementUrl);
             return false;
         }
    }
                diff --git a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
index 639668f..e3ee409 100644
--- a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.managers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.util.Time;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
@@ -41,7 +42,7 @@ import java.util.Set;
  */
 public class UserSessionManager {
 
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UserSessionManager.class);
 
     private final KeycloakSession kcSession;
     private final UserSessionPersisterProvider persister;
@@ -136,7 +137,7 @@ public class UserSessionManager {
     public boolean isOfflineTokenAllowed(ClientSessionModel clientSession) {
         RoleModel offlineAccessRole = clientSession.getRealm().getRole(Constants.OFFLINE_ACCESS_ROLE);
         if (offlineAccessRole == null) {
-            logger.roleNotInRealm(Constants.OFFLINE_ACCESS_ROLE);
+            ServicesLogger.LOGGER.roleNotInRealm(Constants.OFFLINE_ACCESS_ROLE);
             return false;
         }
 
                diff --git a/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java b/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
index 7d390ba..d8c5dee 100755
--- a/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UsersSyncManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.managers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.cluster.ClusterEvent;
 import org.keycloak.cluster.ClusterListener;
 import org.keycloak.cluster.ClusterProvider;
@@ -43,7 +44,7 @@ public class UsersSyncManager {
 
     private static final String FEDERATION_TASK_KEY = "federation";
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UsersSyncManager.class);
 
     /**
      * Check federationProviderModel of all realms and possibly start periodic sync for them
@@ -177,7 +178,7 @@ public class UsersSyncManager {
                             logger.debugf("Ignored periodic full sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
                         }
                     } catch (Throwable t) {
-                        logger.errorDuringFullUserSync(t);
+                        ServicesLogger.LOGGER.errorDuringFullUserSync(t);
                     }
                 }
 
@@ -200,7 +201,7 @@ public class UsersSyncManager {
                             logger.debugf("Ignored periodic changed-users sync with federation provider %s due small time since last sync", fedProvider.getDisplayName());
                         }
                     } catch (Throwable t) {
-                        logger.errorDuringChangedUserSync(t);
+                        ServicesLogger.LOGGER.errorDuringChangedUserSync(t);
                     }
                 }
 
                diff --git a/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java b/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java
index eaca98f..05b07f2 100755
--- a/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/UserStorageSyncManager.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.managers;
 
+import org.jboss.logging.Logger;
 import org.keycloak.cluster.ClusterEvent;
 import org.keycloak.cluster.ClusterListener;
 import org.keycloak.cluster.ClusterProvider;
@@ -44,7 +45,7 @@ public class UserStorageSyncManager {
 
     private static final String USER_STORAGE_TASK_KEY = "user-storage";
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UserStorageSyncManager.class);
 
     /**
      * Check federationProviderModel of all realms and possibly start periodic sync for them
@@ -194,7 +195,7 @@ public class UserStorageSyncManager {
                             logger.debugf("Ignored periodic full sync with storage provider %s due small time since last sync", provider.getName());
                         }
                     } catch (Throwable t) {
-                        logger.errorDuringFullUserSync(t);
+                        ServicesLogger.LOGGER.errorDuringFullUserSync(t);
                     }
                 }
 
@@ -217,7 +218,7 @@ public class UserStorageSyncManager {
                             logger.debugf("Ignored periodic changed-users sync with storage provider %s due small time since last sync", provider.getName());
                         }
                     } catch (Throwable t) {
-                        logger.errorDuringChangedUserSync(t);
+                        ServicesLogger.LOGGER.errorDuringChangedUserSync(t);
                     }
                 }
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
index 17b4995..f5a1b27 100755
--- a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.AbstractOAuthClient;
@@ -29,7 +30,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.Auth;
 import org.keycloak.services.managers.AuthenticationManager;
@@ -57,7 +57,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public abstract class AbstractSecuredLocalService {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(AbstractSecuredLocalService.class);
 
     private static final String KEYCLOAK_STATE_CHECKER = "KEYCLOAK_STATE_CHECKER";
 
                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 feee73e..2684483 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.util.UriUtils;
 import org.keycloak.credential.CredentialModel;
 import org.keycloak.events.Details;
@@ -86,7 +87,7 @@ import java.util.UUID;
  */
 public class AccountService extends AbstractSecuredLocalService {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(AccountService.class);
 
     private static Set<String> VALID_PATHS = new HashSet<String>();
     static {
@@ -643,12 +644,12 @@ public class AccountService extends AbstractSecuredLocalService {
             errorEvent.error(Errors.NOT_ALLOWED);
             return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
         } catch (ModelException me) {
-            logger.failedToUpdatePassword(me);
+            ServicesLogger.LOGGER.failedToUpdatePassword(me);
             setReferrerOnPage();
             errorEvent.detail(Details.REASON, me.getMessage()).error(Errors.PASSWORD_REJECTED);
             return account.setError(me.getMessage(), me.getParameters()).createResponse(AccountPages.PASSWORD);
         } catch (Exception ape) {
-            logger.failedToUpdatePassword(ape);
+            ServicesLogger.LOGGER.failedToUpdatePassword(ape);
             setReferrerOnPage();
             errorEvent.detail(Details.REASON, ape.getMessage()).error(Errors.PASSWORD_REJECTED);
             return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
index afbec5f..cd4d881 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java
@@ -17,6 +17,7 @@
 package org.keycloak.services.resources.admin;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
@@ -32,7 +33,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.Urls;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.AuthenticationManager;
@@ -70,7 +70,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class AdminConsole {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AdminConsole.class);
 
     @Context
     protected UriInfo uriInfo;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java
index 0fa484d..39be678 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.common.util.Time;
 import org.keycloak.events.EventListenerProvider;
@@ -38,7 +39,7 @@ import java.util.List;
 
 public class AdminEventBuilder {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AdminEventBuilder.class);
 
     private EventStoreProvider store;
     private List<EventListenerProvider> listeners;
@@ -54,7 +55,7 @@ public class AdminEventBuilder {
             if (store != null) {
                 this.store = store;
             } else {
-                logger.noEventStoreProvider();
+                ServicesLogger.LOGGER.noEventStoreProvider();
             }
         }
 
@@ -65,7 +66,7 @@ public class AdminEventBuilder {
                 if (listener != null) {
                     listeners.add(listener);
                 } else {
-                    logger.providerNotFound(id);
+                    ServicesLogger.LOGGER.providerNotFound(id);
                 }
             }
         }
@@ -214,7 +215,7 @@ public class AdminEventBuilder {
             try {
                 store.onEvent(adminEvent, includeRepresentation);
             } catch (Throwable t) {
-                logger.failedToSaveEvent(t);
+                ServicesLogger.LOGGER.failedToSaveEvent(t);
             }
         }
 
@@ -223,7 +224,7 @@ public class AdminEventBuilder {
                 try {
                     l.onEvent(adminEvent, includeRepresentation);
                 } catch (Throwable t) {
-                    logger.failedToSendType(t, l);
+                    ServicesLogger.LOGGER.failedToSendType(t, l);
                 }
             }
         }
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
index 87d9091..5a6f4f1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminRoot.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
 import org.jboss.resteasy.spi.NoLogWebApplicationException;
@@ -32,7 +33,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.RealmManager;
@@ -61,7 +61,7 @@ import java.util.Properties;
  */
 @Path("/admin")
 public class AdminRoot {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AdminRoot.class);
 
     @Context
     protected UriInfo uriInfo;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
index b02dbb4..a767833 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AttackDetectionResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.events.admin.OperationType;
@@ -24,7 +25,6 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserLoginFailureModel;
 import org.keycloak.models.UserModel;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.BruteForceProtector;
 
 import javax.ws.rs.DELETE;
@@ -46,7 +46,7 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class AttackDetectionResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AttackDetectionResource.class);
     protected RealmAuth auth;
     protected RealmModel realm;
     private AdminEventBuilder adminEvent;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index cc4605d..087022f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotFoundException;
@@ -48,7 +49,6 @@ import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
 import org.keycloak.representations.idm.ConfigPropertyRepresentation;
 import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.utils.CredentialHelper;
 
 import javax.ws.rs.Consumes;
@@ -83,7 +83,7 @@ public class AuthenticationManagementResource {
     @Context
     private UriInfo uriInfo;
 
-    private static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(AuthenticationManagementResource.class);
 
     public AuthenticationManagementResource(RealmModel realm, KeycloakSession session, RealmAuth auth, AdminEventBuilder adminEvent) {
         this.realm = realm;
@@ -290,7 +290,7 @@ public class AuthenticationManagementResource {
 
         String newName = data.get("newName");
         if (realm.getFlowByAlias(newName) != null) {
-            return Response.status(Response.Status.CONFLICT).build();
+            return ErrorResponse.exists("New flow alias name already exists");
         }
 
         AuthenticationFlowModel flow = realm.getFlowByAlias(flowAlias);
@@ -310,7 +310,7 @@ public class AuthenticationManagementResource {
         data.put("id", copy.getId());
         adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
 
-        return Response.status(201).build();
+        return Response.status(Response.Status.CREATED).build();
 
     }
 
@@ -344,12 +344,12 @@ public class AuthenticationManagementResource {
     @POST
     @NoCache
     @Consumes(MediaType.APPLICATION_JSON)
-    public void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
+    public Response addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
         auth.requireManage();
 
         AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
         if (parentFlow == null) {
-            throw new BadRequestException("Parent flow doesn't exists");
+            return ErrorResponse.error("Parent flow doesn't exists", Response.Status.BAD_REQUEST);
         }
         String alias = data.get("alias");
         String type = data.get("type");
@@ -359,7 +359,7 @@ public class AuthenticationManagementResource {
 
         AuthenticationFlowModel newFlow = realm.getFlowByAlias(alias);
         if (newFlow != null) {
-            throw new BadRequestException("New flow alias name already exists");
+            return ErrorResponse.exists("New flow alias name already exists");
         }
         newFlow = new AuthenticationFlowModel();
         newFlow.setAlias(alias);
@@ -377,6 +377,8 @@ public class AuthenticationManagementResource {
 
         data.put("id", execution.getId());
         adminEvent.operation(OperationType.CREATE).resource(ResourceType.AUTH_EXECUTION_FLOW).resourcePath(uriInfo).representation(data).success();
+
+        return Response.status(Response.Status.CREATED).build();
     }
 
     private int getNextPriority(AuthenticationFlowModel parentFlow) {
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index 42de5f3..a363e39 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -43,9 +44,7 @@ import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.representations.idm.UserSessionRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.clientregistration.ClientRegistrationTokenUtils;
-import org.keycloak.services.clientregistration.RegistrationAccessToken;
 import org.keycloak.services.clientregistration.policy.RegistrationAuth;
 import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.managers.RealmManager;
@@ -86,7 +85,7 @@ import static java.lang.Boolean.TRUE;
  * @version $Revision: 1 $
  */
 public class ClientResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ClientResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
     private AdminEventBuilder adminEvent;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
index 9b6c795..7bdeccd 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientRoleMappingsResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
@@ -29,7 +30,6 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -53,7 +53,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class ClientRoleMappingsResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ClientRoleMappingsResource.class);
 
     protected KeycloakSession session;
     protected RealmModel realm;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index 237239c..2cd6d47 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.admin.OperationType;
@@ -28,7 +29,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.ClientManager;
 import org.keycloak.services.validation.ClientValidator;
 import org.keycloak.services.validation.PairwiseClientValidator;
@@ -56,7 +56,7 @@ import java.util.Properties;
  * @version $Revision: 1 $
  */
 public class ClientsResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ClientsResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
     private AdminEventBuilder adminEvent;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
index 761e307..19b5e7d 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -30,8 +31,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ClientTemplateRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
-import org.keycloak.services.resources.KeycloakApplication;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -52,7 +51,7 @@ import javax.ws.rs.core.UriInfo;
  * @version $Revision: 1 $
  */
 public class ClientTemplateResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ClientTemplateResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
     private AdminEventBuilder adminEvent;
@@ -62,13 +61,6 @@ public class ClientTemplateResource {
     @Context
     protected UriInfo uriInfo;
 
-    @Context
-    protected KeycloakApplication keycloak;
-
-    protected KeycloakApplication getKeycloakApplication() {
-        return keycloak;
-    }
-
     public ClientTemplateResource(RealmModel realm, RealmAuth auth, ClientTemplateModel template, KeycloakSession session, AdminEventBuilder adminEvent) {
         this.realm = realm;
         this.auth = auth;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
index fb8a970..d327fc3 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplatesResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.admin.OperationType;
@@ -28,7 +29,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ClientTemplateRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -50,7 +50,7 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public class ClientTemplatesResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ClientTemplatesResource.class);
     protected RealmModel realm;
     private RealmAuth auth;
     private AdminEventBuilder adminEvent;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
index 974dcf6..39f152c 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.component.ComponentModel;
@@ -27,7 +28,6 @@ import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -52,7 +52,7 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public class ComponentResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ComponentResource.class);
 
     protected RealmModel realm;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
index a34a98a..a0e369f 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProviderResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.broker.provider.IdentityProvider;
@@ -41,7 +42,6 @@ import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
 import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation;
 import org.keycloak.representations.idm.IdentityProviderRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -67,7 +67,7 @@ import java.util.Map;
  */
 public class IdentityProviderResource {
 
-    private static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(IdentityProviderResource.class);
 
     private final RealmAuth auth;
     private final RealmModel realm;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index 955fa13..e3765c9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
@@ -32,7 +33,6 @@ import org.keycloak.protocol.ProtocolMapperConfigException;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.resources.admin.RealmAuth.Resource;
 
 import javax.ws.rs.Consumes;
@@ -59,7 +59,7 @@ import java.util.Properties;
  * @version $Revision: 1 $
  */
 public class ProtocolMappersResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ProtocolMappersResource.class);
 
     protected RealmModel realm;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 4f06885..47db45e 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotFoundException;
@@ -54,24 +55,18 @@ import org.keycloak.provider.ProviderFactory;
 import org.keycloak.representations.adapters.action.GlobalRequestResult;
 import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.ComponentTypeRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.GroupRepresentation;
 import org.keycloak.representations.idm.PartialImportRepresentation;
 import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.info.SpiInfoRepresentation;
 import org.keycloak.services.ErrorResponse;
-import org.keycloak.services.ServicesLogger;
-import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy;
-import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicySpi;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.managers.LDAPConnectionTestManager;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.managers.UsersSyncManager;
 import org.keycloak.services.resources.admin.RealmAuth.Resource;
-import org.keycloak.services.resources.admin.info.ServerInfoAdminResource;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -106,7 +101,7 @@ import java.util.regex.PatternSyntaxException;
  * @version $Revision: 1 $
  */
 public class RealmAdminResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
     protected RealmAuth auth;
     protected RealmModel realm;
     private TokenManager tokenManager;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
index 2437dd0..ef72fa7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -31,7 +32,6 @@ import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
 
@@ -58,7 +58,7 @@ import java.util.List;
  * @version $Revision: 1 $
  */
 public class RealmsAdminResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(RealmsAdminResource.class);
     protected AdminAuth auth;
     protected TokenManager tokenManager;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
index 345cae5..1b48933 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleByIdResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
@@ -26,7 +27,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -49,7 +49,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class RoleByIdResource extends RoleResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(RoleByIdResource.class);
     private final RealmModel realm;
     private final RealmAuth auth;
     private AdminEventBuilder adminEvent;
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
index 91f3e95..28985c2 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RoleMapperResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.common.ClientConnection;
@@ -32,7 +33,6 @@ import org.keycloak.representations.idm.ClientMappingsRepresentation;
 import org.keycloak.representations.idm.MappingsRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.services.ErrorResponseException;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.RealmManager;
 
 import javax.ws.rs.Consumes;
@@ -63,7 +63,7 @@ import java.util.Set;
  * @version $Revision: 1 $
  */
 public class RoleMapperResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(RoleMapperResource.class);
 
     protected RealmModel realm;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
index e173cd3..f8cb9e1 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProviderResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
@@ -71,7 +72,7 @@ import java.util.Properties;
  */
 public class UserFederationProviderResource {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UserFederationProviderResource.class);
 
     private final KeycloakSession session;
     private final RealmModel realm;
@@ -118,7 +119,7 @@ public class UserFederationProviderResource {
         new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, model, false);
         boolean kerberosCredsAdded = UserFederationProvidersResource.checkKerberosCredential(session, realm, model);
         if (kerberosCredsAdded) {
-            logger.addedKerberosToRealmCredentials();
+            ServicesLogger.LOGGER.addedKerberosToRealmCredentials();
         }
 
         adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
@@ -410,7 +411,7 @@ public class UserFederationProviderResource {
         UserFederationProviderFactory providerFactory = (UserFederationProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserFederationProvider.class, providerModel.getProviderName());
         UserFederationProvider federationProvider = providerFactory.getInstance(session, providerModel);
 
-        logger.syncingDataForMapper(mapperModel.getName(), mapperModel.getFederationMapperType(), direction);
+        ServicesLogger.LOGGER.syncingDataForMapper(mapperModel.getName(), mapperModel.getFederationMapperType(), direction);
 
         UserFederationSyncResult syncResult;
         if ("fedToKeycloak".equals(direction)) {
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
index 6467dfd..4333c93 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserFederationProvidersResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
@@ -67,7 +68,7 @@ import java.util.Properties;
  * @version $Revision: 1 $
  */
 public class UserFederationProvidersResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UserFederationProvidersResource.class);
 
     protected RealmModel realm;
 
@@ -208,7 +209,7 @@ public class UserFederationProvidersResource {
         new UsersSyncManager().notifyToRefreshPeriodicSync(session, realm, model, false);
         boolean kerberosCredsAdded = checkKerberosCredential(session, realm, model);
         if (kerberosCredsAdded) {
-            logger.addedKerberosToRealmCredentials();
+            ServicesLogger.LOGGER.addedKerberosToRealmCredentials();
         }
 
         rep.setId(model.getId());
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 138af53..f76761f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.NotFoundException;
@@ -107,7 +108,7 @@ import java.util.concurrent.TimeUnit;
  * @version $Revision: 1 $
  */
 public class UsersResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UsersResource.class);
 
     protected RealmModel realm;
 
@@ -538,6 +539,8 @@ public class UsersResource {
             currentRep.put("grantedProtocolMappers", (rep==null ? Collections.emptyMap() : rep.getGrantedProtocolMappers()));
             currentRep.put("grantedRealmRoles", (rep==null ? Collections.emptyList() : rep.getGrantedRealmRoles()));
             currentRep.put("grantedClientRoles", (rep==null ? Collections.emptyMap() : rep.getGrantedClientRoles()));
+            currentRep.put("createdDate", (rep==null ? null : rep.getCreatedDate()));
+            currentRep.put("lastUpdatedDate", (rep==null ? null : rep.getLastUpdatedDate()));
 
             List<Map<String, String>> additionalGrants = new LinkedList<>();
             if (hasOfflineToken) {
@@ -857,7 +860,7 @@ public class UsersResource {
 
             return Response.ok().build();
         } catch (EmailException e) {
-            logger.failedToSendActionsEmail(e);
+            ServicesLogger.LOGGER.failedToSendActionsEmail(e);
             return ErrorResponse.error("Failed to send execute actions email", Response.Status.INTERNAL_SERVER_ERROR);
         }
     }
                diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
index 1112416..9fde51f 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UserStorageProviderResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources.admin;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.common.ClientConnection;
@@ -23,7 +24,6 @@ import org.keycloak.component.ComponentModel;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.UserStorageSyncManager;
 import org.keycloak.storage.UserStorageProvider;
 import org.keycloak.storage.UserStorageProviderModel;
@@ -46,7 +46,7 @@ import java.util.Map;
  * @version $Revision: 1 $
  */
 public class UserStorageProviderResource {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(UserStorageProviderResource.class);
 
     protected RealmModel realm;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
index 5497b57..5170bc2 100755
--- a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
+++ b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.BadRequestException;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.UnauthorizedException;
@@ -33,7 +34,6 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.representations.idm.OAuth2ErrorRepresentation;
 import org.keycloak.services.ForbiddenException;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
@@ -53,7 +53,7 @@ import javax.ws.rs.ext.Providers;
  */
 public class ClientsManagementService {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ClientsManagementService.class);
 
     private RealmModel realm;
 
                diff --git a/services/src/main/java/org/keycloak/services/resources/Cors.java b/services/src/main/java/org/keycloak/services/resources/Cors.java
index 7b4957a..2cd07b1 100755
--- a/services/src/main/java/org/keycloak/services/resources/Cors.java
+++ b/services/src/main/java/org/keycloak/services/resources/Cors.java
@@ -16,12 +16,12 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
 import org.keycloak.common.util.CollectionUtil;
 import org.keycloak.models.ClientModel;
 import org.keycloak.representations.AccessToken;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
@@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit;
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
 public class Cors {
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(Cors.class);
 
     public static final long DEFAULT_MAX_AGE = TimeUnit.HOURS.toSeconds(1);
     public static final String DEFAULT_ALLOW_METHODS = "GET, HEAD, OPTIONS";
                diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index 5464384..a8c4cc4 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.OAuth2Constants;
@@ -99,7 +100,7 @@ import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
  */
 public class IdentityBrokerService implements IdentityProvider.AuthenticationCallback {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(IdentityBrokerService.class);
 
     private final RealmModel realmModel;
 
@@ -856,7 +857,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
                     this.session.getTransactionManager().commit();
                 }
             } catch (Exception e) {
-                logger.couldNotFireEvent(e);
+                ServicesLogger.LOGGER.couldNotFireEvent(e);
                 rollback();
             }
         }
                diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index d425eea..363d6f4 100644
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -20,6 +20,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.jboss.dmr.ModelNode;
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.core.Dispatcher;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.Config;
@@ -87,7 +88,7 @@ public class KeycloakApplication extends Application {
 
     public static final String KEYCLOAK_EMBEDDED = "keycloak.embedded";
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(KeycloakApplication.class);
 
     protected boolean embedded = false;
 
@@ -265,14 +266,14 @@ public class KeycloakApplication extends Application {
             String dmrConfig = loadDmrConfig(context);
             if (dmrConfig != null) {
                 node = new ObjectMapper().readTree(dmrConfig);
-                logger.loadingFrom("standalone.xml or domain.xml");
+                ServicesLogger.LOGGER.loadingFrom("standalone.xml or domain.xml");
             }
 
             String configDir = System.getProperty("jboss.server.config.dir");
             if (node == null && configDir != null) {
                 File f = new File(configDir + File.separator + "keycloak-server.json");
                 if (f.isFile()) {
-                    logger.loadingFrom(f.getAbsolutePath());
+                    ServicesLogger.LOGGER.loadingFrom(f.getAbsolutePath());
                     node = new ObjectMapper().readTree(f);
                 }
             }
@@ -280,7 +281,7 @@ public class KeycloakApplication extends Application {
             if (node == null) {
                 URL resource = Thread.currentThread().getContextClassLoader().getResource("META-INF/keycloak-server.json");
                 if (resource != null) {
-                    logger.loadingFrom(resource);
+                    ServicesLogger.LOGGER.loadingFrom(resource);
                     node = new ObjectMapper().readTree(resource);
                 }
             }
@@ -370,23 +371,23 @@ public class KeycloakApplication extends Application {
                 manager.setContextPath(getContextPath());
 
                 if (rep.getId() != null && manager.getRealm(rep.getId()) != null) {
-                    logger.realmExists(rep.getRealm(), from);
+                    ServicesLogger.LOGGER.realmExists(rep.getRealm(), from);
                     exists = true;
                 }
 
                 if (manager.getRealmByName(rep.getRealm()) != null) {
-                    logger.realmExists(rep.getRealm(), from);
+                    ServicesLogger.LOGGER.realmExists(rep.getRealm(), from);
                     exists = true;
                 }
                 if (!exists) {
                     RealmModel realm = manager.importRealm(rep);
-                    logger.importedRealm(realm.getName(), from);
+                    ServicesLogger.LOGGER.importedRealm(realm.getName(), from);
                 }
                 session.getTransactionManager().commit();
             } catch (Throwable t) {
                 session.getTransactionManager().rollback();
                 if (!exists) {
-                    logger.unableToImportRealm(t, rep.getRealm(), from);
+                    ServicesLogger.LOGGER.unableToImportRealm(t, rep.getRealm(), from);
                 }
             }
         } finally {
@@ -399,14 +400,14 @@ public class KeycloakApplication extends Application {
         if (configDir != null) {
             File addUserFile = new File(configDir + File.separator + "keycloak-add-user.json");
             if (addUserFile.isFile()) {
-                logger.imprtingUsersFrom(addUserFile);
+                ServicesLogger.LOGGER.imprtingUsersFrom(addUserFile);
 
                 List<RealmRepresentation> realms;
                 try {
                     realms = JsonSerialization.readValue(new FileInputStream(addUserFile), new TypeReference<List<RealmRepresentation>>() {
                     });
                 } catch (IOException e) {
-                    logger.failedToLoadUsers(e);
+                    ServicesLogger.LOGGER.failedToLoadUsers(e);
                     return;
                 }
 
@@ -418,7 +419,7 @@ public class KeycloakApplication extends Application {
 
                             RealmModel realm = session.realms().getRealmByName(realmRep.getRealm());
                             if (realm == null) {
-                                logger.addUserFailedRealmNotFound(userRep.getUsername(), realmRep.getRealm());
+                                ServicesLogger.LOGGER.addUserFailedRealmNotFound(userRep.getUsername(), realmRep.getRealm());
                             } else {
                                 UserModel user = session.users().addUser(realm, userRep.getUsername());
                                 user.setEnabled(userRep.isEnabled());
@@ -427,13 +428,13 @@ public class KeycloakApplication extends Application {
                             }
 
                             session.getTransactionManager().commit();
-                            logger.addUserSuccess(userRep.getUsername(), realmRep.getRealm());
+                            ServicesLogger.LOGGER.addUserSuccess(userRep.getUsername(), realmRep.getRealm());
                         } catch (ModelDuplicateException e) {
                             session.getTransactionManager().rollback();
-                            logger.addUserFailedUserExists(userRep.getUsername(), realmRep.getRealm());
+                            ServicesLogger.LOGGER.addUserFailedUserExists(userRep.getUsername(), realmRep.getRealm());
                         } catch (Throwable t) {
                             session.getTransactionManager().rollback();
-                            logger.addUserFailed(t, userRep.getUsername(), realmRep.getRealm());
+                            ServicesLogger.LOGGER.addUserFailed(t, userRep.getUsername(), realmRep.getRealm());
                         } finally {
                             session.close();
                         }
@@ -441,7 +442,7 @@ public class KeycloakApplication extends Application {
                 }
 
                 if (!addUserFile.delete()) {
-                    logger.failedToDeleteFile(addUserFile.getAbsolutePath());
+                    ServicesLogger.LOGGER.failedToDeleteFile(addUserFile.getAbsolutePath());
                 }
             }
         }
                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 f85c2a1..2e2641c 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.keycloak.OAuth2Constants;
 import org.keycloak.authentication.AuthenticationProcessor;
@@ -86,7 +87,7 @@ import java.net.URI;
  */
 public class LoginActionsService {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(LoginActionsService.class);
 
     public static final String ACTION_COOKIE = "KEYCLOAK_ACTION";
     public static final String AUTHENTICATE_PATH = "authenticate";
@@ -239,7 +240,7 @@ public class LoginActionsService {
                             return false;
                         }
                     } catch (Exception e) {
-                        logger.failedToParseRestartLoginCookie(e);
+                        ServicesLogger.LOGGER.failedToParseRestartLoginCookie(e);
                     }
                 }
                 event.error(Errors.INVALID_CODE);
@@ -281,7 +282,7 @@ public class LoginActionsService {
 
             final UserSessionModel userSession = clientSession.getUserSession();
             if (userSession == null) {
-                logger.userSessionNull();
+                ServicesLogger.LOGGER.userSessionNull();
                 event.error(Errors.USER_SESSION_NOT_FOUND);
                 throw new WebApplicationException(ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE));
             }
@@ -579,7 +580,7 @@ public class LoginActionsService {
         String noteKey = firstBrokerLogin ? AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE : PostBrokerLoginConstants.PBL_BROKERED_IDENTITY_CONTEXT;
         SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromClientSession(clientSessionn, noteKey);
         if (serializedCtx == null) {
-            logger.notFoundSerializedCtxInClientSession(noteKey);
+            ServicesLogger.LOGGER.notFoundSerializedCtxInClientSession(noteKey);
             throw new WebApplicationException(ErrorPage.error(session, "Not found serialized context in clientSession."));
         }
         BrokeredIdentityContext brokerContext = serializedCtx.deserialize(session, clientSessionn);
@@ -587,12 +588,12 @@ public class LoginActionsService {
 
         String flowId = firstBrokerLogin ? brokerContext.getIdpConfig().getFirstBrokerLoginFlowId() : brokerContext.getIdpConfig().getPostBrokerLoginFlowId();
         if (flowId == null) {
-            logger.flowNotConfigForIDP(identityProviderAlias);
+            ServicesLogger.LOGGER.flowNotConfigForIDP(identityProviderAlias);
             throw new WebApplicationException(ErrorPage.error(session, "Flow not configured for identity provider"));
         }
         AuthenticationFlowModel brokerLoginFlow = realm.getAuthenticationFlowById(flowId);
         if (brokerLoginFlow == null) {
-            logger.flowNotFoundForIDP(flowId, identityProviderAlias);
+            ServicesLogger.LOGGER.flowNotFoundForIDP(flowId, identityProviderAlias);
             throw new WebApplicationException(ErrorPage.error(session, "Flow not found for identity provider"));
         }
 
@@ -702,7 +703,7 @@ public class LoginActionsService {
             ClientSessionCode accessCode = checks.clientCode;
             ClientSessionModel clientSession = accessCode.getClientSession();
             if (!ClientSessionModel.Action.VERIFY_EMAIL.name().equals(clientSession.getNote(AuthenticationManager.CURRENT_REQUIRED_ACTION))) {
-                logger.reqdActionDoesNotMatch();
+                ServicesLogger.LOGGER.reqdActionDoesNotMatch();
                 event.error(Errors.INVALID_CODE);
                 throw new WebApplicationException(ErrorPage.error(session, Messages.STALE_VERIFY_EMAIL_LINK));
             }
@@ -715,7 +716,7 @@ public class LoginActionsService {
             String keyFromSession = clientSession.getNote(Constants.VERIFY_EMAIL_KEY);
             clientSession.removeNote(Constants.VERIFY_EMAIL_KEY);
             if (!key.equals(keyFromSession)) {
-                logger.invalidKeyForEmailVerification();
+                ServicesLogger.LOGGER.invalidKeyForEmailVerification();
                 event.error(Errors.INVALID_USER_CREDENTIALS);
                 throw new WebApplicationException(ErrorPage.error(session, Messages.INVALID_CODE));
             }
@@ -859,7 +860,7 @@ public class LoginActionsService {
 
         RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, action);
         if (factory == null) {
-            logger.actionProviderNull();
+            ServicesLogger.LOGGER.actionProviderNull();
             event.error(Errors.INVALID_CODE);
             throw new WebApplicationException(ErrorPage.error(session, Messages.INVALID_CODE));
         }
                diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
index 0b41e51..227719d 100755
--- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
@@ -24,7 +25,6 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.idm.PublishedRealmRepresentation;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.resources.admin.AdminRoot;
 
 import javax.ws.rs.GET;
@@ -43,7 +43,7 @@ import javax.ws.rs.core.UriInfo;
  * @version $Revision: 1 $
  */
 public class PublicRealmResource {
-    protected static final  ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(PublicRealmResource.class);
 
     @Context
     protected UriInfo uriInfo;
                diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index a6cf072..f30665b 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.authorization.AuthorizationProvider;
@@ -29,7 +30,6 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.LoginProtocol;
 import org.keycloak.protocol.LoginProtocolFactory;
-import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.clientregistration.ClientRegistrationService;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resource.RealmResourceProvider;
@@ -57,7 +57,7 @@ import java.net.URI;
  */
 @Path("/realms")
 public class RealmsResource {
-    protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(RealmsResource.class);
 
     @Context
     protected KeycloakSession session;
                diff --git a/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java b/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java
index a3db764..0352c08 100755
--- a/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/ServerVersionResource.java
@@ -16,11 +16,11 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
 import org.keycloak.representations.VersionRepresentation;
-import org.keycloak.services.ServicesLogger;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.OPTIONS;
@@ -37,7 +37,7 @@ import javax.ws.rs.core.Response;
 @Path("/version")
 public class ServerVersionResource {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ServerVersionResource.class);
 
     @Context
     protected HttpRequest request;
                diff --git a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
index 7cb2379..5c29bfa 100644
--- a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.keycloak.common.Version;
 import org.keycloak.common.util.MimeTypeUtil;
 import org.keycloak.models.KeycloakSession;
@@ -39,7 +40,7 @@ import java.io.InputStream;
 @Path("/resources")
 public class ThemeResource {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(ThemeResource.class);
 
     @Context
     private KeycloakSession session;
@@ -69,7 +70,7 @@ public class ThemeResource {
                 return Response.status(Response.Status.NOT_FOUND).build();
             }
         } catch (Exception e) {
-            logger.failedToGetThemeRequest(e);
+            ServicesLogger.LOGGER.failedToGetThemeRequest(e);
             return Response.serverError().build();
         }
     }
                diff --git a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
index d57f0fe..48d2650 100755
--- a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
@@ -16,6 +16,7 @@
  */
 package org.keycloak.services.resources;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.common.util.MimeTypeUtil;
@@ -63,7 +64,7 @@ import java.util.Map;
 @Path("/")
 public class WelcomeResource {
 
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    protected static final Logger logger = Logger.getLogger(WelcomeResource.class);
 
     private static final String KEYCLOAK_STATE_CHECKER = "KEYCLOAK_STATE_CHECKER";
 
@@ -110,7 +111,7 @@ public class WelcomeResource {
             return createWelcomePage(null, null);
         } else {
             if (!isLocal()) {
-                logger.rejectedNonLocalAttemptToCreateInitialUser(session.getContext().getConnection().getRemoteAddr());
+                ServicesLogger.LOGGER.rejectedNonLocalAttemptToCreateInitialUser(session.getContext().getConnection().getRemoteAddr());
                 throw new WebApplicationException(Response.Status.BAD_REQUEST);
             }
 
@@ -139,10 +140,10 @@ public class WelcomeResource {
                 bootstrap = false;
                 applianceBootstrap.createMasterRealmUser(username, password);
 
-                logger.createdInitialAdminUser(username);
+                ServicesLogger.LOGGER.createdInitialAdminUser(username);
                 return createWelcomePage("User created", null);
             } else {
-                logger.initialUserAlreadyCreated();
+                ServicesLogger.LOGGER.initialUserAlreadyCreated();
                 return createWelcomePage(null, "Users already exists");
             }
         }
                diff --git a/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java b/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
index da9c876..9b8bc40 100644
--- a/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
+++ b/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.services.scheduled;
 
+import org.jboss.logging.Logger;
 import org.keycloak.cluster.ClusterProvider;
 import org.keycloak.cluster.ExecutionResult;
 import org.keycloak.models.KeycloakSession;
@@ -32,6 +33,8 @@ import java.util.concurrent.Callable;
  */
 public class ClusterAwareScheduledTaskRunner extends ScheduledTaskRunner {
 
+    private static final Logger logger = Logger.getLogger(ClusterAwareScheduledTaskRunner.class);
+
     private final int intervalSecs;
 
     public ClusterAwareScheduledTaskRunner(KeycloakSessionFactory sessionFactory, ScheduledTask task, long intervalMillis) {
                diff --git a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
index 81ff5f6..3c3e8e2 100644
--- a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
+++ b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.services.scheduled;
 
+import org.jboss.logging.Logger;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.services.ServicesLogger;
@@ -27,7 +28,7 @@ import org.keycloak.timer.ScheduledTask;
  */
 public class ScheduledTaskRunner implements Runnable {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(ScheduledTaskRunner.class);
 
     protected final KeycloakSessionFactory sessionFactory;
     protected final ScheduledTask task;
@@ -43,14 +44,14 @@ public class ScheduledTaskRunner implements Runnable {
         try {
             runTask(session);
         } catch (Throwable t) {
-            logger.failedToRunScheduledTask(t, task.getClass().getSimpleName());
+            ServicesLogger.LOGGER.failedToRunScheduledTask(t, task.getClass().getSimpleName());
 
             session.getTransactionManager().rollback();
         } finally {
             try {
                 session.close();
             } catch (Throwable t) {
-                logger.failedToCloseProviderSession(t);
+                ServicesLogger.LOGGER.failedToCloseProviderSession(t);
             }
         }
     }
                diff --git a/services/src/main/java/org/keycloak/services/ServicesLogger.java b/services/src/main/java/org/keycloak/services/ServicesLogger.java
index 6418a61..b0e0cca 100644
--- a/services/src/main/java/org/keycloak/services/ServicesLogger.java
+++ b/services/src/main/java/org/keycloak/services/ServicesLogger.java
@@ -47,7 +47,7 @@ import static org.jboss.logging.Logger.Level.WARN;
 @MessageLogger(projectCode="KC-SERVICES", length=4)
 public interface ServicesLogger extends BasicLogger {
 
-    ServicesLogger ROOT_LOGGER = Logger.getMessageLogger(ServicesLogger.class, "org.keycloak.services");
+    ServicesLogger LOGGER = Logger.getMessageLogger(ServicesLogger.class, "org.keycloak.services");
 
     @LogMessage(level = INFO)
     @Message(id=1, value="Loading config from %s")
                diff --git a/services/src/main/java/org/keycloak/transaction/JBossJtaTransactionManagerLookup.java b/services/src/main/java/org/keycloak/transaction/JBossJtaTransactionManagerLookup.java
index 9d0be4a..2f3e895 100644
--- a/services/src/main/java/org/keycloak/transaction/JBossJtaTransactionManagerLookup.java
+++ b/services/src/main/java/org/keycloak/transaction/JBossJtaTransactionManagerLookup.java
@@ -16,9 +16,9 @@
  */
 package org.keycloak.transaction;
 
+import org.jboss.logging.Logger;
 import org.keycloak.Config;
 import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.services.ServicesLogger;
 
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
@@ -29,7 +29,7 @@ import javax.transaction.TransactionManager;
  * @version $Revision: 1 $
  */
 public class JBossJtaTransactionManagerLookup implements JtaTransactionManagerLookup {
-    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(JBossJtaTransactionManagerLookup.class);
     private TransactionManager tm;
 
     @Override
                diff --git a/services/src/main/java/org/keycloak/utils/CredentialHelper.java b/services/src/main/java/org/keycloak/utils/CredentialHelper.java
index 7db006a..b3f9678 100755
--- a/services/src/main/java/org/keycloak/utils/CredentialHelper.java
+++ b/services/src/main/java/org/keycloak/utils/CredentialHelper.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.utils;
 
+import org.jboss.logging.Logger;
 import org.keycloak.authentication.Authenticator;
 import org.keycloak.authentication.AuthenticatorFactory;
 import org.keycloak.authentication.ClientAuthenticator;
@@ -28,7 +29,6 @@ import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.models.AuthenticationFlowModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
-import org.keycloak.services.ServicesLogger;
 
 /**
  * used to set an execution a state based on type.
@@ -38,7 +38,7 @@ import org.keycloak.services.ServicesLogger;
  */
 public class CredentialHelper {
 
-    protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+    private static final Logger logger = Logger.getLogger(CredentialHelper.class);
 
     public static void setRequiredCredential(KeycloakSession session, String type, RealmModel realm) {
         AuthenticationExecutionModel.Requirement requirement = AuthenticationExecutionModel.Requirement.REQUIRED;
                diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractKeycloakIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractKeycloakIdentityProviderTest.java
index 9cad056..ed1e757 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractKeycloakIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractKeycloakIdentityProviderTest.java
@@ -242,7 +242,7 @@ public abstract class AbstractKeycloakIdentityProviderTest extends AbstractIdent
      * Test for KEYCLOAK-1053 - verify email action is not performed if email is not provided, login is normal, but action stays in set to be performed later
      */
     @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() throws Exception {
         RealmModel realm = getRealm();
         realm.setVerifyEmail(true);
         setUpdateProfileFirstLogin(realm, IdentityProviderRepresentation.UPFLM_OFF);
                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 0552875..58c4ca1 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
@@ -151,7 +151,7 @@ public class OIDCKeyCloakServerBrokerBasicTest extends AbstractKeycloakIdentityP
     }
 
     @Test
-    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() {
+    public void testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled() throws Exception {
         super.testSuccessfulAuthenticationWithoutUpdateProfile_emailNotProvided_emailVerifyEnabled();
     }
 
                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 9b7f0d2..9fe49f2 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
@@ -105,12 +105,16 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertTrue(isRoleGranted(realm, "realm-role", johnFooConsent));
         Assert.assertTrue(isRoleGranted(barClient, "bar-client-role", johnFooConsent));
         Assert.assertTrue(isMapperGranted(fooClient, "foo", johnFooConsent));
+        Assert.assertNotNull("Created Date should be set", johnFooConsent.getCreatedDate());
+        Assert.assertNotNull("Last Updated Date should be set", johnFooConsent.getLastUpdatedDate());
 
         UserConsentModel johnBarConsent = realmManager.getSession().users().getConsentByClient(realm, john.getId(), barClient.getId());
         Assert.assertEquals(johnBarConsent.getGrantedRoles().size(), 1);
         Assert.assertEquals(johnBarConsent.getGrantedProtocolMappers().size(), 1);
         Assert.assertTrue(isRoleGranted(realm, "realm-role", johnBarConsent));
         Assert.assertTrue(isMapperGranted(barClient, "bar", johnBarConsent));
+        Assert.assertNotNull("Created Date should be set", johnBarConsent.getCreatedDate());
+        Assert.assertNotNull("Last Updated Date should be set", johnBarConsent.getLastUpdatedDate());
 
         UserConsentModel maryConsent = realmManager.getSession().users().getConsentByClient(realm, mary.getId(), fooClient.getId());
         Assert.assertEquals(maryConsent.getGrantedRoles().size(), 1);
@@ -118,6 +122,8 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertTrue(isRoleGranted(realm, "realm-role", maryConsent));
         Assert.assertFalse(isRoleGranted(barClient, "bar-client-role", maryConsent));
         Assert.assertTrue(isMapperGranted(fooClient, "foo", maryConsent));
+        Assert.assertNotNull("Created Date should be set", maryConsent.getCreatedDate());
+        Assert.assertNotNull("Last Updated Date should be set", maryConsent.getLastUpdatedDate());
 
         Assert.assertNull(realmManager.getSession().users().getConsentByClient(realm, mary.getId(), barClient.getId()));
     }
@@ -176,6 +182,7 @@ public class UserConsentModelTest extends AbstractModelTest {
         Assert.assertFalse(isRoleGranted(realm, "realm-role", johnConsent));
         Assert.assertTrue(isRoleGranted(realm, "new-realm-role", johnConsent));
         Assert.assertFalse(isMapperGranted(fooClient, "foo", johnConsent));
+        Assert.assertTrue("Created date should be less than last updated date", johnConsent.getCreatedDate() < johnConsent.getLastUpdatedDate());
     }
 
     @Test
                diff --git a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-kc-oidc.json b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-kc-oidc.json
index 767ab44..05cb0e9 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-kc-oidc.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-broker-realm-with-kc-oidc.json
@@ -26,8 +26,8 @@
                     "claim.name": "mobile",
                     "Claim JSON Type": "String",
                     "access.token.claim": "true",
-                    "id.token.claim": "true"
-
+                    "id.token.claim": "true",
+                    "userinfo.token.claim": "true"
                 }
             },
             {
@@ -40,8 +40,8 @@
                     "claim.name": "preferred_username",
                     "Claim JSON Type": "String",
                     "access.token.claim": "true",
-                    "id.token.claim": "true"
-
+                    "id.token.claim": "true",
+                    "userinfo.token.claim": "true"
                 }
             },
             {
@@ -54,8 +54,8 @@
                     "claim.name": "email",
                     "Claim JSON Type": "String",
                     "access.token.claim": "true",
-                    "id.token.claim": "true"
-
+                    "id.token.claim": "true",
+                    "userinfo.token.claim": "true"
                 }
             },
             {
@@ -68,8 +68,8 @@
                     "claim.name": "given_name",
                     "Claim JSON Type": "String",
                     "access.token.claim": "true",
-                    "id.token.claim": "true"
-
+                    "id.token.claim": "true",
+                    "userinfo.token.claim": "true"
                 }
             },
             {
@@ -83,7 +83,6 @@
                     "Claim JSON Type": "String",
                     "access.token.claim": "true",
                     "id.token.claim": "true"
-
                 }
             },
             {
@@ -93,8 +92,8 @@
                 "consentRequired": false,
                 "config": {
                     "access.token.claim": "true",
-                    "id.token.claim": "true"
-
+                    "id.token.claim": "true",
+                    "userinfo.token.claim": "true"
                 }
             }
 
                testsuite/integration-arquillian/pom.xml 19(+19 -0)
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index d63f76b..49c9604 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -49,6 +49,10 @@
         <version.shrinkwrap.resolvers>2.2.2</version.shrinkwrap.resolvers>
         <undertow-embedded.version>1.0.0.Alpha2</undertow-embedded.version>
 
+        <!--migration properties-->
+        <migration.project.version>2.2.1.Final</migration.project.version>
+        <migration.product.version>1.9.8.Final</migration.product.version>
+        
         <maven.compiler.target>1.8</maven.compiler.target>
         <maven.compiler.source>1.8</maven.compiler.source>
     </properties>
@@ -128,5 +132,20 @@
         <module>servers</module>
         <module>tests</module>
     </modules>
+    
+    <profiles>
+        <profile>
+            <id>test-project-migration</id>
+            <properties>
+                <migrated.auth.server.version>${migration.project.version}</migrated.auth.server.version>
+            </properties>
+        </profile>
+        <profile>
+            <id>test-product-migration</id>
+            <properties>
+                <migrated.auth.server.version>${migration.product.version}</migrated.auth.server.version>
+            </properties>
+        </profile>
+    </profiles>
 
 </project>
                diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/migration-strategy.xsl b/testsuite/integration-arquillian/servers/auth-server/jboss/common/migration-strategy.xsl
new file mode 100644
index 0000000..5bc33b8
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/migration-strategy.xsl
@@ -0,0 +1,57 @@
+<!--
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xalan="http://xml.apache.org/xalan"
+                version="2.0"
+                exclude-result-prefixes="xalan">
+
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+    <xsl:strip-space elements="*"/>
+
+    <xsl:param name="migration.strategy" />
+    <xsl:param name="initialize.empty" />
+    
+    <xsl:variable name="nsKS" select="'urn:jboss:domain:keycloak-server'"/>
+
+    <!--set migrationStrategy-->
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='spi' and starts-with(namespace-uri(), $nsKS) and @name='connectionsJpa']
+                         /*[local-name()='provider' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='properties' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='property' and starts-with(namespace-uri(), $nsKS) and @name='migrationStrategy']">
+        <property name="migrationStrategy" value="{$migration.strategy}"/>
+    </xsl:template>
+
+    <!--set initializeEmpty-->
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='spi' and starts-with(namespace-uri(), $nsKS) and @name='connectionsJpa']
+                         /*[local-name()='provider' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='properties' and starts-with(namespace-uri(), $nsKS)]
+                         /*[local-name()='property' and starts-with(namespace-uri(), $nsKS) and @name='initializeEmpty']">
+        <property name="initializeEmpty" value="{$initialize.empty}"/>
+    </xsl:template>
+
+    <!--copy everything else-->
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" />
+        </xsl:copy>
+    </xsl:template>
+
+</xsl:stylesheet>
+
                diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
index e62c79e..dc65870 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
@@ -571,6 +571,60 @@
                 </pluginManagement>
             </build>
         </profile>
+        
+        <profile>
+            <id>migration-manual</id>
+            <activation>
+                <property>
+                    <name>migration.mode</name>
+                    <value>manual</value>
+                </property>
+            </activation>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.codehaus.mojo</groupId>
+                            <artifactId>xml-maven-plugin</artifactId>
+                            <executions>
+                                <execution>
+                                    <id>set-manual-migration-strategy</id>
+                                    <phase>process-resources</phase>
+                                    <goals>
+                                        <goal>transform</goal>
+                                    </goals>
+                                    <configuration>
+                                        <skip></skip>
+                                        <transformationSets>
+                                            <transformationSet>
+                                                <dir>${auth.server.home}/standalone/configuration</dir>
+                                                <includes>
+                                                    <include>standalone.xml</include>
+                                                </includes>
+                                                <stylesheet>${common.resources}/migration-strategy.xsl</stylesheet>
+                                                <outputDir>${auth.server.home}/standalone/configuration</outputDir>
+                                                <parameters>
+                                                    <parameter>
+                                                        <name>migration.strategy</name>
+                                                        <value>manual</value>
+                                                    </parameter>
+                                                    <parameter>
+                                                        <name>initialize.empty</name>
+                                                        <value>false</value>
+                                                    </parameter>
+                                                </parameters>
+                                            </transformationSet>
+                                        </transformationSets>
+                                    </configuration>
+                                </execution>
+                            </executions>
+                        </plugin>
+                
+                    </plugins>
+                </pluginManagement>
+            </build>
+        </profile>
+        
         <profile>
             <id>auth-server-apply-patch</id>
             <activation>
                diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java
index 2a1a911..4092501 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/components/TestImplProviderFactory.java
@@ -36,12 +36,12 @@ import static org.keycloak.provider.ProviderConfigProperty.STRING_TYPE;
 public class TestImplProviderFactory implements TestProviderFactory {
 
     private List<ProviderConfigProperty> config = ProviderConfigurationBuilder.create()
-            .property("secret", "Secret", "A secret value", STRING_TYPE, null, true)
-            .property("number", "Number", "A number value", STRING_TYPE, null, false)
-            .property("required", "Required", "A required value", STRING_TYPE, null, false)
-            .property("val1", "Value 1", "Some more values", STRING_TYPE, null, false)
-            .property("val2", "Value 2", "Some more values", STRING_TYPE, null, false)
-            .property("val3", "Value 3", "Some more values", STRING_TYPE, null, false)
+            .property("secret", "Secret", "A secret value", STRING_TYPE, null, null, true)
+            .property("number", "Number", "A number value", STRING_TYPE, null, null, false)
+            .property("required", "Required", "A required value", STRING_TYPE, null, null, false)
+            .property("val1", "Value 1", "Some more values", STRING_TYPE, null, null, false)
+            .property("val2", "Value 2", "Some more values", STRING_TYPE, null, null, false)
+            .property("val3", "Value 3", "Some more values", STRING_TYPE, null, null, false)
             .build();
 
     @Override
                diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
index 9542eaa..bdeda57 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
@@ -64,7 +64,8 @@ public class AuthServerTestEnricher {
     private static final String AUTH_SERVER_CLUSTER_PROPERTY = "auth.server.cluster";
     public static final boolean AUTH_SERVER_CLUSTER = Boolean.parseBoolean(System.getProperty(AUTH_SERVER_CLUSTER_PROPERTY, "false"));
 
-    private static final Boolean AUTO_MIGRATION_ENABLED = "auto".equals(System.getProperty("migration.mode"));
+    private static final Boolean START_MIGRATION_CONTAINER = "auto".equals(System.getProperty("migration.mode")) || 
+            "manual".equals(System.getProperty("migration.mode"));
 
     @Inject
     @SuiteScoped
@@ -130,7 +131,7 @@ public class AuthServerTestEnricher {
             throw new RuntimeException(String.format("No auth server container matching '%sN' found in arquillian.xml.", authServerBackend));
         }
 
-        if (AUTO_MIGRATION_ENABLED) {
+        if (START_MIGRATION_CONTAINER) {
             // init migratedAuthServerInfo
             for (ContainerInfo container : suiteContext.getContainers()) {
                 // migrated auth server
                diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
index d610957..fe3bce8 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
@@ -49,9 +49,9 @@ import static org.keycloak.testsuite.util.IOUtil.loadJson;
 import static org.keycloak.testsuite.util.IOUtil.loadXML;
 import static org.keycloak.testsuite.util.IOUtil.modifyDocElementAttribute;
 import static org.keycloak.testsuite.util.IOUtil.modifyDocElementValue;
-import static org.keycloak.testsuite.util.IOUtil.removeElementFromDoc;
+import static org.keycloak.testsuite.util.IOUtil.removeElementsFromDoc;
+
 
-;
 
 /**
  * @author tkyjovsk
@@ -97,7 +97,7 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
         if (archive.contains(adapterConfigPath)) {
             log.info("Modifying adapter config " + adapterConfigPath + " in " + archive.getName());
             if (adapterConfigPath.equals(SAML_ADAPTER_CONFIG_PATH)) { // SAML adapter config
-                log.info("Modyfying saml adapter config in " + archive.getName());
+                log.info("Modifying saml adapter config in " + archive.getName());
 
                 Document doc = loadXML(archive.get("WEB-INF/keycloak-saml.xml").getAsset().openStream());
                 if (authServerSslRequired) {
@@ -148,7 +148,17 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
                 } catch (IOException ex) {
                     log.log(Level.FATAL, "Cannot serialize adapter config to JSON.", ex);
                 }
+
+                log.info("Adding OIDCFilter dependencies to " + archive.getName());
+                ((WebArchive) archive).addAsLibraries(KeycloakDependenciesResolver.resolveDependencies("org.keycloak:keycloak-servlet-filter-adapter:" + System.getProperty("project.version")));
+
             }
+
+        } else if (archive.getName().equals("customer-portal-subsystem.war")) {
+
+            log.info("Adding OIDCFilter dependencies to " + archive.getName());
+            ((WebArchive) archive).addAsLibraries(KeycloakDependenciesResolver.resolveDependencies("org.keycloak:keycloak-servlet-filter-adapter:" + System.getProperty("project.version")));
+
         }
     }
 
@@ -210,9 +220,11 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
                 appendChildInDocument(webXmlDoc, "web-app", filterMapping);
 
                 //finally we need to remove all keycloak related configuration from web.xml
-                removeElementFromDoc(webXmlDoc, "web-app", "security-constraint");
-                removeElementFromDoc(webXmlDoc, "web-app", "login-config");
-                removeElementFromDoc(webXmlDoc, "web-app", "security-role");
+                removeElementsFromDoc(webXmlDoc, "web-app", "security-constraint");
+                removeElementsFromDoc(webXmlDoc, "web-app", "login-config");
+                removeElementsFromDoc(webXmlDoc, "web-app", "security-role");
+
+
             }
 
 
                diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
index 015910b..345e77e 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
@@ -129,7 +129,7 @@ public class IOUtil {
         node.setTextContent(node.getTextContent().replace(regex, replacement));
     }
 
-    public static void removeElementFromDoc(Document doc, String parentTag, String removeNode) {
+    public static void removeElementsFromDoc(Document doc, String parentTag, String removeNode) {
         NodeList nodes = doc.getElementsByTagName(parentTag);
         if (nodes.getLength() != 1) {
             log.warn("Not able or ambiguous to find element: " + parentTag);
@@ -143,18 +143,23 @@ public class IOUtil {
         }
 
         NodeList removeNodes = parentElement.getElementsByTagName(removeNode);
-        if (removeNodes.getLength() != 1) {
-            log.warn("Not able or ambiguous to find element: " + removeNode + " within node " + parentTag);
+        if (removeNodes == null) {
+            log.warn("Not able to find element: " + removeNode + " within node " + parentTag);
             return;
         }
 
-        Element removeElement = (Element) removeNodes.item(0);
-        if (removeElement == null) {
-            log.warn("Not able to find element: " + removeNode + " within node " + parentTag);
-            return;
+        for (int i = 0; i < removeNodes.getLength();){
+            Element removeElement = (Element) removeNodes.item(i);
+            if (removeElement == null) {
+                log.warn("Not able to find element: " + removeNode + " within node " + parentTag);
+                return;
+            }
+
+            log.info("Removing node " + removeNode);
+            parentElement.removeChild(removeElement);
+
         }
 
-        parentElement.removeChild(removeElement);
     }
 
     public static String getElementTextContent(Document doc, String path) {
                diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
index fc54023..fb39ec5 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
@@ -49,7 +49,7 @@ public class UserInfoClientUtil {
         return client.target(userInfoUri);
     }
 
-    public static void testSuccessfulUserInfoResponse(Response response, String expectedUsername, String expectedEmail) {
+    public static UserInfo testSuccessfulUserInfoResponse(Response response, String expectedUsername, String expectedEmail) {
         Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
         Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JSON);
 
@@ -61,6 +61,7 @@ public class UserInfoClientUtil {
         Assert.assertNotNull(userInfo.getSubject());
         Assert.assertEquals(expectedEmail, userInfo.getEmail());
         Assert.assertEquals(expectedUsername, userInfo.getPreferredUsername());
+        return userInfo;
     }
 
 }
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
index 5bd733c..676a40f 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
@@ -278,6 +278,14 @@ public abstract class AbstractKeycloakTest {
         }
     }
 
+    /**
+     * Creates a user in the given realm and returns its ID.
+     * @param realm Realm name
+     * @param username Username
+     * @param password Password
+     * @param requiredActions
+     * @return ID of the newly created user
+     */
     public String createUser(String realm, String username, String password, String ... requiredActions) {
         List<String> requiredUserActions = Arrays.asList(requiredActions);
 
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
index 63821b3..4317317 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
@@ -70,6 +70,7 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
                 modifyClientUrls(tr, "^(/.*)", appServerContextRootPage.toString() + "$1");
                 modifySamlMasterURLs(tr, "8080", System.getProperty("auth.server.http.port", null));
                 modifySAMLClientsAttributes(tr, "8080", System.getProperty("app.server.http.port", "8280"));
+                modifyClientJWKSUrl(tr, "^(/.*)", appServerContextRootPage.toString() + "$1");
             }
             if ("true".equals(System.getProperty("auth.server.ssl.required"))) {
                 tr.setSslRequired("all");
@@ -77,6 +78,16 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
         }
     }
 
+    private void modifyClientJWKSUrl(RealmRepresentation realm, String regex, String replacement) {
+        if (realm.getClients() != null) {
+            realm.getClients().stream().filter(client -> "client-jwt".equals(client.getClientAuthenticatorType())).forEach(client -> {
+                Map<String, String> attr = client.getAttributes();
+                attr.put("jwks.url", attr.get("jwks.url").replaceFirst(regex, replacement));
+                client.setAttributes(attr);
+            });
+        }
+    }
+
     public abstract void addAdapterTestRealms(List<RealmRepresentation> testRealms);
 
     public boolean isRelative() {
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java
new file mode 100644
index 0000000..b53fdcc
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java
@@ -0,0 +1,42 @@
+package org.keycloak.testsuite.adapter.servlet;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.keycloak.testsuite.arquillian.annotation.UseServletFilter;
+
+/**
+ * Created by zschwarz on 9/14/16.
+ */
+
+@UseServletFilter(filterName = "oidc-filter", filterClass = "org.keycloak.adapters.servlet.KeycloakOIDCFilter")
+public abstract class AbstractDemoFilterServletAdapterTest extends AbstractDemoServletsAdapterTest {
+
+
+    @Test
+    @Override
+    @Ignore
+    public void testCustomerPortalWithSubsystemSettings() {
+
+    }
+
+    @Test
+    @Override
+    @Ignore
+    public void testAuthenticated() {
+
+    }
+
+    @Test
+    @Override
+    @Ignore
+    public void testOIDCParamsForwarding() {
+
+    }
+
+    @Test
+    @Override
+    @Ignore
+    public void testClientWithJwksUri() {
+
+    }
+}
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java
index 07c5beb..ab934fe 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ComponentsTest.java
@@ -20,25 +20,13 @@ package org.keycloak.testsuite.admin;
 import org.junit.Before;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.ComponentsResource;
-import org.keycloak.common.util.CertificateUtils;
-import org.keycloak.common.util.KeyUtils;
 import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.common.util.PemUtils;
-import org.keycloak.keys.Attributes;
-import org.keycloak.keys.KeyProvider;
-import org.keycloak.keys.RsaKeyProviderFactory;
 import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.representations.idm.ErrorRepresentation;
-import org.keycloak.representations.idm.KeysMetadataRepresentation;
-import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.components.TestImplProviderFactory;
 import org.keycloak.testsuite.components.TestProvider;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.Response;
-import java.math.BigInteger;
-import java.security.KeyPair;
-import java.security.PublicKey;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
index f44cc2e..7e61f51 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
@@ -45,20 +45,30 @@ import javax.ws.rs.core.Response;
 import java.io.IOException;
 import java.net.URI;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import java.util.UUID;
+import javax.ws.rs.ClientErrorException;
+import static org.hamcrest.Matchers.*;
+
+import static org.junit.Assert.*;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.models.AdminRoles;
 import static org.keycloak.testsuite.Assert.assertNames;
+import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
+import org.keycloak.testsuite.auth.page.AuthRealm;
+import org.keycloak.testsuite.util.GroupBuilder;
 
 /**
  * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
  */
 public class GroupTest extends AbstractGroupTest {
 
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
     @Override
     public void addTestRealms(List<RealmRepresentation> testRealms) {
         RealmRepresentation testRealmRep = loadTestRealm(testRealms);
@@ -293,26 +303,24 @@ public class GroupTest extends AbstractGroupTest {
     @Test
     public void updateGroup() {
         RealmResource realm = adminClient.realms().realm("test");
+        final String groupName = "group-" + UUID.randomUUID();
 
-        GroupRepresentation group = new GroupRepresentation();
-        group.setName("group");
-
-        Map<String, List<String>> attrs = new HashMap<>();
-        attrs.put("attr1", Collections.singletonList("attrval1"));
-        attrs.put("attr2", Collections.singletonList("attrval2"));
-        group.setAttributes(attrs);
+        GroupRepresentation group = GroupBuilder.create()
+          .name(groupName)
+          .singleAttribute("attr1", "attrval1")
+          .singleAttribute("attr2", "attrval2")
+          .build();
         createGroup(realm, group);
-        group = realm.getGroupByPath("/group");
+        group = realm.getGroupByPath("/" + groupName);
 
         Assert.assertNotNull(group);
-        assertEquals("group", group.getName());
-        assertEquals(2, group.getAttributes().size());
-        assertEquals(1, group.getAttributes().get("attr1").size());
-        assertEquals("attrval1", group.getAttributes().get("attr1").get(0));
-        assertEquals(1, group.getAttributes().get("attr2").size());
-        assertEquals("attrval2", group.getAttributes().get("attr2").get(0));
+        assertThat(group.getName(), is(groupName));
+        assertThat(group.getAttributes().keySet(), containsInAnyOrder("attr1", "attr2"));
+        assertThat(group.getAttributes(), hasEntry(is("attr1"), contains("attrval1")));
+        assertThat(group.getAttributes(), hasEntry(is("attr2"), contains("attrval2")));
 
-        group.setName("group-new");
+        final String groupNewName = "group-" + UUID.randomUUID();
+        group.setName(groupNewName);
 
         group.getAttributes().remove("attr1");
         group.getAttributes().get("attr2").add("attrval2-2");
@@ -321,12 +329,12 @@ public class GroupTest extends AbstractGroupTest {
         realm.groups().group(group.getId()).update(group);
         assertAdminEvents.assertEvent("test", OperationType.UPDATE, AdminEventPaths.groupPath(group.getId()), group, ResourceType.GROUP);
 
-        group = realm.getGroupByPath("/group-new");
+        group = realm.getGroupByPath("/" + groupNewName);
 
-        assertEquals("group-new", group.getName());
-        assertEquals(2, group.getAttributes().size());
-        assertEquals(2, group.getAttributes().get("attr2").size());
-        assertEquals(1, group.getAttributes().get("attr3").size());
+        assertThat(group.getName(), is(groupNewName));
+        assertThat(group.getAttributes().keySet(), containsInAnyOrder("attr2", "attr3"));
+        assertThat(group.getAttributes(), hasEntry(is("attr2"), containsInAnyOrder("attrval2", "attrval2-2")));
+        assertThat(group.getAttributes(), hasEntry(is("attr3"), contains("attrval2")));
     }
 
     @Test
@@ -457,4 +465,117 @@ public class GroupTest extends AbstractGroupTest {
         assertNames(roles.clientLevel(clientId).listAll(), "client-composite");
     }
 
+
+    /**
+     * Verifies that the user does not have access to Keycloak Admin endpoint when role is not
+     * assigned to that user.
+     * @link https://issues.jboss.org/browse/KEYCLOAK-2964
+     */
+    @Test
+    public void noAdminEndpointAccessWhenNoRoleAssigned() {
+        String userName = "user-" + UUID.randomUUID();
+        final String realmName = AuthRealm.MASTER;
+        createUser(realmName, userName, "pwd");
+
+        Keycloak userClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
+          realmName, userName, "pwd", Constants.ADMIN_CLI_CLIENT_ID);
+
+        expectedException.expect(ClientErrorException.class);
+        expectedException.expectMessage(String.valueOf(Response.Status.FORBIDDEN.getStatusCode()));
+        userClient.realms().findAll();  // Any admin operation will do
+    }
+
+    /**
+     * Verifies that the role assigned to a user is correctly handled by Keycloak Admin endpoint.
+     * @link https://issues.jboss.org/browse/KEYCLOAK-2964
+     */
+    @Test
+    public void adminEndpointAccessibleWhenAdminRoleAssignedToUser() {
+        String userName = "user-" + UUID.randomUUID();
+
+        final String realmName = AuthRealm.MASTER;
+        RealmResource realm = adminClient.realms().realm(realmName);
+        RoleRepresentation adminRole = realm.roles().get(AdminRoles.ADMIN).toRepresentation();
+        assertThat(adminRole, notNullValue());
+        assertThat(adminRole.getId(), notNullValue());
+
+        String userId = createUser(realmName, userName, "pwd");
+        assertThat(userId, notNullValue());
+
+        RoleMappingResource mappings = realm.users().get(userId).roles();
+        mappings.realmLevel().add(Collections.singletonList(adminRole));
+
+        Keycloak userClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
+          realmName, userName, "pwd", Constants.ADMIN_CLI_CLIENT_ID);
+
+        assertThat(userClient.realms().findAll(),  // Any admin operation will do
+          not(empty()));
+    }
+
+    /**
+     * Verifies that the role assigned to a user's group is correctly handled by Keycloak Admin endpoint.
+     * @link https://issues.jboss.org/browse/KEYCLOAK-2964
+     */
+    @Test
+    public void adminEndpointAccessibleWhenAdminRoleAssignedToGroup() {
+        String userName = "user-" + UUID.randomUUID();
+        String groupName = "group-" + UUID.randomUUID();
+
+        final String realmName = AuthRealm.MASTER;
+        RealmResource realm = adminClient.realms().realm(realmName);
+        RoleRepresentation adminRole = realm.roles().get(AdminRoles.ADMIN).toRepresentation();
+        assertThat(adminRole, notNullValue());
+        assertThat(adminRole.getId(), notNullValue());
+
+        String userId = createUser(realmName, userName, "pwd");
+        GroupRepresentation group = GroupBuilder.create().name(groupName).build();
+        Response response = realm.groups().add(group);
+        String groupId = ApiUtil.getCreatedId(response);
+        response.close();
+
+        RoleMappingResource mappings = realm.groups().group(groupId).roles();
+        mappings.realmLevel().add(Collections.singletonList(adminRole));
+
+        realm.users().get(userId).joinGroup(groupId);
+
+        Keycloak userClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
+          realmName, userName, "pwd", Constants.ADMIN_CLI_CLIENT_ID);
+
+        assertThat(userClient.realms().findAll(),  // Any admin operation will do
+          not(empty()));
+    }
+
+
+    /**
+     * Verifies that the role assigned to a user's group is correctly handled by Keycloak Admin endpoint.
+     * @link https://issues.jboss.org/browse/KEYCLOAK-2964
+     */
+    @Test
+    public void adminEndpointAccessibleWhenAdminRoleAssignedToGroupAfterUserJoinedIt() {
+        String userName = "user-" + UUID.randomUUID();
+        String groupName = "group-" + UUID.randomUUID();
+
+        final String realmName = AuthRealm.MASTER;
+        RealmResource realm = adminClient.realms().realm(realmName);
+        RoleRepresentation adminRole = realm.roles().get(AdminRoles.ADMIN).toRepresentation();
+        assertThat(adminRole, notNullValue());
+        assertThat(adminRole.getId(), notNullValue());
+
+        String userId = createUser(realmName, userName, "pwd");
+        GroupRepresentation group = GroupBuilder.create().name(groupName).build();
+        Response response = realm.groups().add(group);
+        String groupId = ApiUtil.getCreatedId(response);
+        response.close();
+
+        realm.users().get(userId).joinGroup(groupId);
+
+        RoleMappingResource mappings = realm.groups().group(groupId).roles();
+        mappings.realmLevel().add(Collections.singletonList(adminRole));
+
+        Keycloak userClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
+          realmName, userName, "pwd", Constants.ADMIN_CLI_CLIENT_ID);
+
+        assertThat(userClient.realms().findAll(),  // Any admin operation will do
+          not(empty()));
+    }
 }
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCPairwiseClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCPairwiseClientRegistrationTest.java
index ca4553d..c5bb785 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCPairwiseClientRegistrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCPairwiseClientRegistrationTest.java
@@ -27,6 +27,7 @@ import org.keycloak.client.registration.ClientRegistrationException;
 import org.keycloak.client.registration.HttpErrorException;
 import org.keycloak.protocol.oidc.mappers.SHA256PairwiseSubMapper;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.UserInfo;
 import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
 import org.keycloak.representations.idm.ClientInitialAccessPresentation;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
@@ -38,7 +39,9 @@ import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
 import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
 import org.keycloak.testsuite.util.ClientManager;
 import org.keycloak.testsuite.util.OAuthClient;
+import org.keycloak.testsuite.util.UserInfoClientUtil;
 
+import javax.ws.rs.client.Client;
 import javax.ws.rs.core.Response;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -323,5 +326,17 @@ public class OIDCPairwiseClientRegistrationTest extends AbstractClientRegistrati
         // Assert pairwise client has different subject like userId
         String pairwiseUserId = accessToken.getSubject();
         Assert.assertNotEquals(pairwiseUserId, user.getId());
+
+        // Send request to userInfo endpoint
+        Client jaxrsClient = javax.ws.rs.client.ClientBuilder.newClient();
+        try {
+            // Check that userInfo contains pairwise subjectId as well
+            Response userInfoResponse = UserInfoClientUtil.executeUserInfoRequest_getMethod(jaxrsClient, accessTokenResponse.getAccessToken());
+            UserInfo userInfo = UserInfoClientUtil.testSuccessfulUserInfoResponse(userInfoResponse, "test-user", "test-user@localhost");
+            String userInfoSubId = userInfo.getSubject();
+            Assert.assertEquals(pairwiseUserId, userInfoSubId);
+        } finally {
+            jaxrsClient.close();
+        }
     }
 }
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
index 9889d13..d9c041c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
@@ -36,10 +36,8 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
 import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
 import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.idm.GroupRepresentation;
 import org.keycloak.representations.idm.RequiredActionProviderRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
 import static org.keycloak.testsuite.Assert.*;
 import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
 
@@ -49,6 +47,8 @@ import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER;
 public class MigrationTest extends AbstractKeycloakTest {
 
     private final String MIGRATION = "Migration";
+    private RealmResource migrationRealm;
+    private RealmResource masterRealm;
         
     @Override
     public void addTestRealms(List<RealmRepresentation> testRealms) {
@@ -57,66 +57,74 @@ public class MigrationTest extends AbstractKeycloakTest {
     
     @Before
     public void beforeMigrationTest() {
+        migrationRealm = adminClient.realms().realm(MIGRATION);
+        masterRealm = adminClient.realms().realm(MASTER);
+        
         //add migration realm to testRealmReps to make the migration removed after test
         testRealmReps.add(adminClient.realms().realm(MIGRATION).toRepresentation());
     }
     
     @Test
     @Migration(versionFrom = "1.9.8.Final")
-    public void migration198Test() {
-        RealmResource migrationRealm = adminClient.realms().realm(MIGRATION);
-        RealmResource masterRealm = adminClient.realms().realm(MASTER);
-        
-        testMigratedMasterData(masterRealm);
-        testMigratedMigrationData(migrationRealm);
-        
-        // 2.0.0 - org.keycloak.migration.migrators.MigrateTo2_0_0
-        testAuthorizationServices(masterRealm, migrationRealm);
-        
-        // 2.1.0 - org.keycloak.migration.migrators.MigrateTo2_1_0
-        testNameOfOTPRequiredAction(masterRealm, migrationRealm);
-        //there is no migration of RolePolicies (MigrateTo2_1_0#migrateRolePolicies) between 1.9.8 to current version (2.3.0-SNAPSHOT)
-        
-        // 2.2.0 - org.keycloak.migration.migrators.MigrateTo2_2_0
-        testIdentityProviderAuthenticator(masterRealm, migrationRealm);
+    public void migration1_9_8Test() {
+        testMigratedData();
+        testMigrationTo2_0_0();
+        testMigrationTo2_1_0();
+        testMigrationTo2_2_0();
     }
     
     @Test
     @Migration(versionFrom = "2.2.1.Final")
-    public void migration221Test() {
-        RealmResource migrationRealm = adminClient.realms().realm(MIGRATION);
-        RealmResource masterRealm = adminClient.realms().realm(MASTER);
-        
-        testMigratedMasterData(masterRealm);
-        testMigratedMigrationData(migrationRealm);
-        
-        // so far nothing else
+    public void migration2_2_1Test() {
+        testMigratedData();
     }
     
-    private void testMigratedMasterData(RealmResource master) {
-        assertNames(master.roles().list(), "offline_access", "uma_authorization", "create-realm", "master-test-realm-role", "admin");
-        assertNames(master.clients().findAll(), "admin-cli", "security-admin-console", "broker", "account", 
+    private void testMigratedData() {
+        //master realm
+        assertNames(masterRealm.roles().list(), "offline_access", "uma_authorization", "create-realm", "master-test-realm-role", "admin");
+        assertNames(masterRealm.clients().findAll(), "admin-cli", "security-admin-console", "broker", "account", 
                 "master-realm", "master-test-client", "Migration-realm");
-        String id = master.clients().findByClientId("master-test-client").get(0).getId();
-        assertNames(master.clients().get(id).roles().list(), "master-test-client-role");
-        assertNames(master.users().search("", 0, 5), "admin", "master-test-user");
-        assertNames(master.groups().groups(), "master-test-group");
+        String id = masterRealm.clients().findByClientId("master-test-client").get(0).getId();
+        assertNames(masterRealm.clients().get(id).roles().list(), "master-test-client-role");
+        assertNames(masterRealm.users().search("", 0, 5), "admin", "master-test-user");
+        assertNames(masterRealm.groups().groups(), "master-test-group");
+        
+        //migrationRealm
+        assertNames(migrationRealm.roles().list(), "offline_access", "uma_authorization", "migration-test-realm-role");
+        assertNames(migrationRealm.clients().findAll(), "account", "admin-cli", "broker", "migration-test-client", "realm-management", "security-admin-console");
+        String id2 = migrationRealm.clients().findByClientId("migration-test-client").get(0).getId();
+        assertNames(migrationRealm.clients().get(id2).roles().list(), "migration-test-client-role");
+        assertNames(migrationRealm.users().search("", 0, 5), "migration-test-user");
+        assertNames(migrationRealm.groups().groups(), "migration-test-group");
+    }
+    
+    /**
+     * @see org.keycloak.migration.migrators.MigrateTo2_0_0
+     */
+    private void testMigrationTo2_0_0() {
+        testAuthorizationServices(masterRealm, migrationRealm);
     }
     
-    private void testMigratedMigrationData(RealmResource migration) {
-        assertNames(migration.roles().list(), "offline_access", "uma_authorization", "migration-test-realm-role");
-        assertNames(migration.clients().findAll(), "account", "admin-cli", "broker", "migration-test-client", "realm-management", "security-admin-console");
-        String id = migration.clients().findByClientId("migration-test-client").get(0).getId();
-        assertNames(migration.clients().get(id).roles().list(), "migration-test-client-role");
-        assertNames(migration.users().search("", 0, 5), "migration-test-user");
-        assertNames(migration.groups().groups(), "migration-test-group");
+    /**
+     * @see org.keycloak.migration.migrators.MigrateTo2_1_0
+     */
+    private void testMigrationTo2_1_0() {
+        testNameOfOTPRequiredAction(masterRealm, migrationRealm);
+    }
+    
+    /**
+     * @see org.keycloak.migration.migrators.MigrateTo2_2_0
+     */
+    private void testMigrationTo2_2_0() {
+        testIdentityProviderAuthenticator(masterRealm, migrationRealm);
+        //MigrateTo2_2_0#migrateRolePolicies is not relevant any more
     }
     
     private void testAuthorizationServices(RealmResource... realms) {
         for (RealmResource realm : realms) {
             //test setup of authorization services
             for (String roleName : Constants.AUTHZ_DEFAULT_AUTHORIZATION_ROLES) {
-                RoleResource role = realm.roles().get(roleName); //throw javax.ws.rs.NotFoundException
+                RoleResource role = realm.roles().get(roleName); //throws javax.ws.rs.NotFoundException if not found
 
                 assertFalse("Role's scopeParamRequired should be false.", role.toRepresentation().isScopeParamRequired());
                 assertFalse("Role shouldn't be composite should be false.", role.toRepresentation().isComposite());
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 13c1ea4..eaeeafd 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -674,138 +674,6 @@ public class AccessTokenTest extends AbstractKeycloakTest {
     }
 
     @Test
-    public void testTokenMapping() throws Exception {
-        Client client = javax.ws.rs.client.ClientBuilder.newClient();
-        UriBuilder builder = UriBuilder.fromUri(AUTH_SERVER_ROOT);
-        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
-        WebTarget grantTarget = client.target(grantUri);
-        {
-            UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
-            UserRepresentation user = userResource.toRepresentation();
-
-            user.singleAttribute("street", "5 Yawkey Way");
-            user.singleAttribute("locality", "Boston");
-            user.singleAttribute("region", "MA");
-            user.singleAttribute("postal_code", "02115");
-            user.singleAttribute("country", "USA");
-            user.singleAttribute("phone", "617-777-6666");
-
-            List<String> departments = Arrays.asList("finance", "development");
-            user.getAttributes().put("departments", departments);
-            userResource.update(user);
-
-            ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
-
-            ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
-            app.getProtocolMappers().createMapper(mapper);
-
-            ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
-            app.getProtocolMappers().createMapper(hard);
-            app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
-            app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
-            app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
-            app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
-            app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
-            app.getProtocolMappers().createMapper(createHardcodedRole("hard-app", "app.hardcoded"));
-            app.getProtocolMappers().createMapper(createRoleNameMapper("rename-app-role", "test-app.customer-user", "realm-user"));
-        }
-
-        {
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            assertEquals(200, response.getStatus());
-
-            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
-            IDToken idToken = getIdToken(tokenResponse);
-            assertNotNull(idToken.getAddress());
-            assertEquals(idToken.getName(), "Tom Brady");
-            assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
-            assertEquals(idToken.getAddress().getLocality(), "Boston");
-            assertEquals(idToken.getAddress().getRegion(), "MA");
-            assertEquals(idToken.getAddress().getPostalCode(), "02115");
-            assertEquals(idToken.getAddress().getCountry(), "USA");
-            assertNotNull(idToken.getOtherClaims().get("home_phone"));
-            assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
-            assertEquals("coded", idToken.getOtherClaims().get("hard"));
-            Map nested = (Map) idToken.getOtherClaims().get("nested");
-            assertEquals("coded-nested", nested.get("hard"));
-            nested = (Map) idToken.getOtherClaims().get("home");
-            assertEquals("617-777-6666", nested.get("phone"));
-            List<String> departments = (List<String>) idToken.getOtherClaims().get("department");
-            assertEquals(2, departments.size());
-            assertTrue(departments.contains("finance") && departments.contains("development"));
-
-            AccessToken accessToken = getAccessToken(tokenResponse);
-            assertEquals(accessToken.getName(), "Tom Brady");
-            assertNotNull(accessToken.getAddress());
-            assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
-            assertEquals(accessToken.getAddress().getLocality(), "Boston");
-            assertEquals(accessToken.getAddress().getRegion(), "MA");
-            assertEquals(accessToken.getAddress().getPostalCode(), "02115");
-            assertEquals(accessToken.getAddress().getCountry(), "USA");
-            assertNotNull(accessToken.getOtherClaims().get("home_phone"));
-            assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
-            assertEquals("coded", accessToken.getOtherClaims().get("hard"));
-            nested = (Map) accessToken.getOtherClaims().get("nested");
-            assertEquals("coded-nested", nested.get("hard"));
-            nested = (Map) accessToken.getOtherClaims().get("home");
-            assertEquals("617-777-6666", nested.get("phone"));
-            departments = (List<String>) idToken.getOtherClaims().get("department");
-            assertEquals(2, departments.size());
-            assertTrue(departments.contains("finance") && departments.contains("development"));
-            assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
-            assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
-            Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
-            assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
-
-
-            response.close();
-        }
-
-        // undo mappers
-        {
-            ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
-            ClientRepresentation clientRepresentation = app.toRepresentation();
-            for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
-                if (model.getName().equals("address")
-                        || model.getName().equals("hard")
-                        || model.getName().equals("hard-nested")
-                        || model.getName().equals("custom phone")
-                        || model.getName().equals("departments")
-                        || model.getName().equals("nested phone")
-                        || model.getName().equals("rename-app-role")
-                        || model.getName().equals("hard-realm")
-                        || model.getName().equals("hard-app")
-                        ) {
-                    app.getProtocolMappers().delete(model.getId());
-                }
-            }
-        }
-
-        events.clear();
-
-
-        {
-            Response response = executeGrantAccessTokenRequest(grantTarget);
-            assertEquals(200, response.getStatus());
-            org.keycloak.representations.AccessTokenResponse tokenResponse = response.readEntity(org.keycloak.representations.AccessTokenResponse.class);
-            IDToken idToken = getIdToken(tokenResponse);
-            assertNull(idToken.getAddress());
-            assertNull(idToken.getOtherClaims().get("home_phone"));
-            assertNull(idToken.getOtherClaims().get("hard"));
-            assertNull(idToken.getOtherClaims().get("nested"));
-            assertNull(idToken.getOtherClaims().get("department"));
-
-            response.close();
-        }
-
-
-        events.clear();
-        client.close();
-
-
-    }
-
-    @Test
     public void testClientTemplate() throws Exception {
         RealmResource realm = adminClient.realm("test");
         RoleRepresentation realmRole = new RoleRepresentation();
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java
new file mode 100644
index 0000000..d317af7
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.oauth;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ProtocolMappersResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.admin.ApiUtil;
+import org.keycloak.testsuite.util.ClientManager;
+import org.keycloak.testsuite.util.OAuthClient;
+import org.keycloak.testsuite.util.ProtocolMapperUtil;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
+import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
+import static org.keycloak.testsuite.admin.ApiUtil.findClientResourceByClientId;
+import static org.keycloak.testsuite.admin.ApiUtil.findUserByUsernameId;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createAddressMapper;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createClaimMapper;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedClaim;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createHardcodedRole;
+import static org.keycloak.testsuite.util.ProtocolMapperUtil.createRoleNameMapper;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
+
+    @Rule
+    public AssertEvents events = new AssertEvents(this);
+
+
+    @Override
+    public void beforeAbstractKeycloakTest() throws Exception {
+        super.beforeAbstractKeycloakTest();
+    }
+
+    @Before
+    public void clientConfiguration() {
+        ClientManager.realm(adminClient.realm("test")).clientId("test-app").directAccessGrant(true);
+        /*
+         * Configure the default client ID. Seems like OAuthClient is keeping the state of clientID
+         * For example: If some test case configure oauth.clientId("sample-public-client"), other tests
+         * will faile and the clientID will always be "sample-public-client
+         * @see AccessTokenTest#testAuthorizationNegotiateHeaderIgnored()
+         */
+        oauth.clientId("test-app");
+    }
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+        RealmRepresentation realm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
+        testRealms.add(realm);
+    }
+
+
+    @Test
+    public void testTokenMapping() throws Exception {
+        {
+            UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
+            UserRepresentation user = userResource.toRepresentation();
+
+            user.singleAttribute("street", "5 Yawkey Way");
+            user.singleAttribute("locality", "Boston");
+            user.singleAttribute("region", "MA");
+            user.singleAttribute("postal_code", "02115");
+            user.singleAttribute("country", "USA");
+            user.singleAttribute("phone", "617-777-6666");
+
+            List<String> departments = Arrays.asList("finance", "development");
+            user.getAttributes().put("departments", departments);
+            userResource.update(user);
+
+            ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
+
+            ProtocolMapperRepresentation mapper = createAddressMapper(true, true);
+            app.getProtocolMappers().createMapper(mapper);
+
+            ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true);
+            app.getProtocolMappers().createMapper(hard);
+            app.getProtocolMappers().createMapper(createHardcodedClaim("hard-nested", "nested.hard", "coded-nested", "String", false, null, true, true));
+            app.getProtocolMappers().createMapper(createClaimMapper("custom phone", "phone", "home_phone", "String", true, "", true, true, false));
+            app.getProtocolMappers().createMapper(createClaimMapper("nested phone", "phone", "home.phone", "String", true, "", true, true, false));
+            app.getProtocolMappers().createMapper(createClaimMapper("departments", "departments", "department", "String", true, "", true, true, true));
+            app.getProtocolMappers().createMapper(createHardcodedRole("hard-realm", "hardcoded"));
+            app.getProtocolMappers().createMapper(createHardcodedRole("hard-app", "app.hardcoded"));
+            app.getProtocolMappers().createMapper(createRoleNameMapper("rename-app-role", "test-app.customer-user", "realm-user"));
+        }
+
+        {
+            OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
+
+            IDToken idToken = oauth.verifyIDToken(response.getIdToken());
+            assertNotNull(idToken.getAddress());
+            assertEquals(idToken.getName(), "Tom Brady");
+            assertEquals(idToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            assertEquals(idToken.getAddress().getLocality(), "Boston");
+            assertEquals(idToken.getAddress().getRegion(), "MA");
+            assertEquals(idToken.getAddress().getPostalCode(), "02115");
+            assertEquals(idToken.getAddress().getCountry(), "USA");
+            assertNotNull(idToken.getOtherClaims().get("home_phone"));
+            assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone"));
+            assertEquals("coded", idToken.getOtherClaims().get("hard"));
+            Map nested = (Map) idToken.getOtherClaims().get("nested");
+            assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map) idToken.getOtherClaims().get("home");
+            assertEquals("617-777-6666", nested.get("phone"));
+            List<String> departments = (List<String>) idToken.getOtherClaims().get("department");
+            assertEquals(2, departments.size());
+            assertTrue(departments.contains("finance") && departments.contains("development"));
+
+            AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
+            assertEquals(accessToken.getName(), "Tom Brady");
+            assertNotNull(accessToken.getAddress());
+            assertEquals(accessToken.getAddress().getStreetAddress(), "5 Yawkey Way");
+            assertEquals(accessToken.getAddress().getLocality(), "Boston");
+            assertEquals(accessToken.getAddress().getRegion(), "MA");
+            assertEquals(accessToken.getAddress().getPostalCode(), "02115");
+            assertEquals(accessToken.getAddress().getCountry(), "USA");
+            assertNotNull(accessToken.getOtherClaims().get("home_phone"));
+            assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone"));
+            assertEquals("coded", accessToken.getOtherClaims().get("hard"));
+            nested = (Map) accessToken.getOtherClaims().get("nested");
+            assertEquals("coded-nested", nested.get("hard"));
+            nested = (Map) accessToken.getOtherClaims().get("home");
+            assertEquals("617-777-6666", nested.get("phone"));
+            departments = (List<String>) idToken.getOtherClaims().get("department");
+            assertEquals(2, departments.size());
+            assertTrue(departments.contains("finance") && departments.contains("development"));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains("hardcoded"));
+            assertTrue(accessToken.getRealmAccess().getRoles().contains("realm-user"));
+            Assert.assertFalse(accessToken.getResourceAccess("test-app").getRoles().contains("customer-user"));
+            assertTrue(accessToken.getResourceAccess("app").getRoles().contains("hardcoded"));
+        }
+
+        // undo mappers
+        {
+            ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
+            ClientRepresentation clientRepresentation = app.toRepresentation();
+            for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
+                if (model.getName().equals("address")
+                        || model.getName().equals("hard")
+                        || model.getName().equals("hard-nested")
+                        || model.getName().equals("custom phone")
+                        || model.getName().equals("departments")
+                        || model.getName().equals("nested phone")
+                        || model.getName().equals("rename-app-role")
+                        || model.getName().equals("hard-realm")
+                        || model.getName().equals("hard-app")
+                        ) {
+                    app.getProtocolMappers().delete(model.getId());
+                }
+            }
+        }
+
+        events.clear();
+
+
+        {
+            OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
+            IDToken idToken = oauth.verifyIDToken(response.getIdToken());
+            assertNull(idToken.getAddress());
+            assertNull(idToken.getOtherClaims().get("home_phone"));
+            assertNull(idToken.getOtherClaims().get("hard"));
+            assertNull(idToken.getOtherClaims().get("nested"));
+            assertNull(idToken.getOtherClaims().get("department"));
+        }
+
+
+        events.clear();
+    }
+
+
+    @Test
+    public void testUserRoleToAttributeMappers() throws Exception {
+        // Add mapper for realm roles
+        ProtocolMapperRepresentation realmMapper = ProtocolMapperUtil.createUserRealmRoleMappingMapper("pref.", "Realm roles mapper", "roles-custom.realm", true, true);
+        ProtocolMapperRepresentation clientMapper = ProtocolMapperUtil.createUserClientRoleMappingMapper("test-app", null, "Client roles mapper", "roles-custom.test-app", true, true);
+
+        ProtocolMappersResource protocolMappers = ApiUtil.findClientResourceByClientId(adminClient.realm("test"), "test-app").getProtocolMappers();
+        protocolMappers.createMapper(Arrays.asList(realmMapper, clientMapper));
+
+        // Login user
+        OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
+        IDToken idToken = oauth.verifyIDToken(response.getIdToken());
+
+        // Verify attribute is filled
+        Map<String, Object> roleMappings = (Map<String, Object>)idToken.getOtherClaims().get("roles-custom");
+        Assert.assertEquals(2, roleMappings.size());
+        String realmRoleMappings = (String) roleMappings.get("realm");
+        String testAppMappings = (String) roleMappings.get("test-app");
+        Assert.assertTrue(realmRoleMappings.contains("pref.user"));
+        Assert.assertEquals("[customer-user]", testAppMappings);
+    }
+
+
+    private ProtocolMapperRepresentation makeMapper(String name, String mapperType, Map<String, String> config) {
+        ProtocolMapperRepresentation rep = new ProtocolMapperRepresentation();
+        rep.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
+        rep.setName(name);
+        rep.setProtocolMapper(mapperType);
+        rep.setConfig(config);
+        rep.setConsentRequired(true);
+        rep.setConsentText("Test Consent Text");
+        return rep;
+    }
+
+}
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/GroupBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/GroupBuilder.java
new file mode 100644
index 0000000..0968ead
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/GroupBuilder.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.util;
+
+import java.util.List;
+import java.util.Map;
+import org.keycloak.representations.idm.GroupRepresentation;
+
+/**
+ *
+ * @author <a href="mailto:hmlnarik@redhat.com">Hynek Mlnarik</a>
+ */
+public class GroupBuilder {
+
+    private final GroupRepresentation rep;
+
+    public static GroupBuilder create() {
+        final GroupRepresentation rep = new GroupRepresentation();
+        return new GroupBuilder(rep);
+    }
+
+    private GroupBuilder(GroupRepresentation rep) {
+        this.rep = rep;
+    }
+
+    public GroupRepresentation build() {
+        return rep;
+    }
+
+    public GroupBuilder id(String id) {
+        rep.setId(id);
+        return this;
+    }
+
+    public GroupBuilder name(String name) {
+        rep.setName(name);
+        return this;
+    }
+
+    public GroupBuilder path(String path) {
+        rep.setPath(path);
+        return this;
+    }
+
+    public GroupBuilder realmRoles(List<String> realmRoles) {
+        rep.setRealmRoles(realmRoles);
+        return this;
+    }
+
+    public GroupBuilder clientRoles(Map<String, List<String>> clientRoles) {
+        rep.setClientRoles(clientRoles);
+        return this;
+    }
+
+    public GroupBuilder attributes(Map<String, List<String>> attributes) {
+        rep.setAttributes(attributes);
+        return this;
+    }
+
+    public GroupBuilder singleAttribute(String name, String value) {
+        rep.singleAttribute(name, value);
+        return this;
+    }
+
+    public GroupBuilder subGroups(List<GroupRepresentation> subGroups) {
+        rep.setSubGroups(subGroups);
+        return this;
+    }
+
+}
                diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java
index 62018e1..6bcea06 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ProtocolMapperUtil.java
@@ -6,6 +6,8 @@ import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
 import org.keycloak.protocol.oidc.mappers.HardcodedRole;
 import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
 import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
+import org.keycloak.protocol.oidc.mappers.UserClientRoleMappingMapper;
+import org.keycloak.protocol.oidc.mappers.UserRealmRoleMappingMapper;
 import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 
@@ -103,4 +105,22 @@ public class ProtocolMapperUtil {
                 consentRequired, consentText,
                 accessToken, idToken));
     }
+
+
+    public static ProtocolMapperRepresentation createUserRealmRoleMappingMapper(String realmRolePrefix,
+                                                                                String name,
+                                                                                String tokenClaimName,
+                                                                                boolean accessToken, boolean idToken) {
+
+        return ModelToRepresentation.toRepresentation(UserRealmRoleMappingMapper.create(realmRolePrefix, name, tokenClaimName, accessToken, idToken));
+    }
+
+
+    public static ProtocolMapperRepresentation createUserClientRoleMappingMapper(String clientId, String clientRolePrefix,
+                                                                                String name,
+                                                                                String tokenClaimName,
+                                                                                boolean accessToken, boolean idToken) {
+
+        return ModelToRepresentation.toRepresentation(UserClientRoleMappingMapper.create(clientId, clientRolePrefix, name, tokenClaimName, accessToken, idToken));
+    }
 }
                diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCFilterAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCFilterAdapterTest.java
new file mode 100644
index 0000000..3427f33
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCFilterAdapterTest.java
@@ -0,0 +1,12 @@
+package org.keycloak.testsuite.adapter;
+
+import org.keycloak.testsuite.adapter.servlet.AbstractDemoFilterServletAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ * Created by zschwarz on 9/14/16.
+ */
+
+@AppServerContainer("app-server-wildfly")
+public class WildflyOIDCFilterAdapterTest extends AbstractDemoFilterServletAdapterTest{
+}
                diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml
index 1683bc9..d30721c 100755
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -405,16 +405,10 @@
             </build>
         </profile>
 
-        <!-- Profile for migration tests-->
+        <!-- Profiles for migration tests-->
         
         <profile>
-            <id>migration-auto</id>
-            <activation>
-                <property>
-                    <name>migration.mode</name>
-                    <value>auto</value>
-                </property>
-            </activation>
+            <id>auth-server-migration</id>
             <properties>
                 <migration.import.props.previous>
                     -Dkeycloak.migration.action=import 
@@ -438,6 +432,9 @@
                                         <requireProperty>
                                             <property>migrated.auth.server.version</property>
                                         </requireProperty>
+                                        <requireProperty>
+                                            <property>migration.mode</property>
+                                        </requireProperty>
                                     </rules>
                                 </configuration>
                             </execution>
                diff --git a/themes/src/main/resources/theme/base/admin/index.ftl b/themes/src/main/resources/theme/base/admin/index.ftl
index 76286b1..7ab0bc9 100755
--- a/themes/src/main/resources/theme/base/admin/index.ftl
+++ b/themes/src/main/resources/theme/base/admin/index.ftl
@@ -22,7 +22,7 @@
     </script>
 
     <script src="${resourceUrl}/lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
-    <script src="${resourceUrl}/lib/select2-3.4.1/select2.js" type="text/javascript"></script>
+    <script src="${resourceUrl}/lib/select2-3.4.1/select2.min.js" type="text/javascript"></script>
 
     <script src="${resourceUrl}/lib/angular/angular.js"></script>
     <script src="${resourceUrl}/lib/angular/angular-resource.js"></script>
                diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index ef27439..ef8ef74 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -896,6 +896,8 @@ spi=SPI
 granted-roles=Granted Roles
 granted-protocol-mappers=Granted Protocol Mappers
 additional-grants=Additional Grants
+consent-created-date=Created
+consent-last-updated-date=Last updated
 revoke=Revoke
 new-password=New Password
 password-confirmation=Password Confirmation
                diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
index 574eb91..9b8a6cb 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
@@ -863,6 +863,8 @@ spi=SPI
 granted-roles=Tildelte roller
 granted-protocol-mappers=Innvilgede protokollmappere
 additional-grants=Tillegsrettigheter
+consent-created-date=Opprettet
+consent-last-updated-date=Sist oppdatert
 revoke=Opphev
 new-password=Nytt passord
 password-confirmation=Passord bekreftelse
                diff --git a/themes/src/main/resources/theme/base/admin/resources/js/app.js b/themes/src/main/resources/theme/base/admin/resources/js/app.js
index f75e66d..e892b45 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/app.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/app.js
@@ -953,6 +953,9 @@ module.config([ '$routeProvider', function($routeProvider) {
                 },
                 mapper : function(ClientProtocolMapperLoader) {
                     return ClientProtocolMapperLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
 
             },
@@ -969,6 +972,9 @@ module.config([ '$routeProvider', function($routeProvider) {
                 },
                 client : function(ClientLoader) {
                     return ClientLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
             controller : 'ClientProtocolMapperCreateCtrl'
@@ -1017,6 +1023,9 @@ module.config([ '$routeProvider', function($routeProvider) {
                 },
                 mapper : function(ClientTemplateProtocolMapperLoader) {
                     return ClientTemplateProtocolMapperLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
 
             },
@@ -1033,6 +1042,9 @@ module.config([ '$routeProvider', function($routeProvider) {
                 },
                 template : function(ClientTemplateLoader) {
                     return ClientTemplateLoader();
+                },
+                clients : function(ClientListLoader) {
+                    return ClientListLoader();
                 }
             },
             controller : 'ClientTemplateProtocolMapperCreateCtrl'
@@ -2802,3 +2814,81 @@ module.directive('kcOnReadFile', function ($parse) {
         }
     };
 });
+
+module.controller('PagingCtrl', function ($scope) {
+    $scope.currentPageInput = 1;
+    
+    $scope.firstPage = function() {
+        if (!$scope.hasPrevious()) return;
+        $scope.currentPage = 1;
+        $scope.currentPageInput = 1;
+    };
+    
+    $scope.lastPage = function() {
+        if (!$scope.hasNext()) return;
+        $scope.currentPage = $scope.numberOfPages;
+        $scope.currentPageInput = $scope.numberOfPages;
+    };
+    
+    $scope.previousPage = function() {
+        if (!$scope.hasPrevious()) return;
+        $scope.currentPage--;
+        $scope.currentPageInput = $scope.currentPage;
+    };
+    
+    $scope.nextPage = function() {
+        if (!$scope.hasNext()) return;
+        $scope.currentPage++;
+        $scope.currentPageInput = $scope.currentPage;
+    };
+    
+    $scope.hasNext = function() {
+        return $scope.currentPage < $scope.numberOfPages;
+    };
+    
+    $scope.hasPrevious = function() {
+        return $scope.currentPage > 1;
+    };
+});
+
+module.directive('kcPaging', function () {
+    return {
+        scope: {
+            currentPage: '=',
+            currentPageInput: '=',
+            numberOfPages: '='
+        },
+        restrict: 'E',
+        replace: true,
+        controller: 'PagingCtrl',
+        templateUrl: resourceUrl + '/templates/kc-paging.html'
+    }
+});
+
+// Tests the page number input from currentPageInput to see
+// if it represents a valid page.  If so, the current page is changed.
+module.directive('kcValidPage', function() {
+   return {
+       require: 'ngModel',
+       link: function(scope, element, attrs, ctrl) {
+           ctrl.$validators.inRange = function(modelValue, viewValue) {
+               if (viewValue >= 1 && viewValue <= scope.numberOfPages) {
+                   scope.currentPage = viewValue;
+               }
+               
+               return true;
+           }
+       }
+   } 
+});
+
+// filter used for paged tables
+module.filter('startFrom', function () {
+    return function (input, start) {
+        if (input) {
+            start = +start;
+            return input.slice(start);
+        }
+        return [];
+    };
+});
\ No newline at end of file
                diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 4b33b14..3405791 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -731,9 +731,21 @@ module.controller('ClientImportCtrl', function($scope, $location, $upload, realm
 });
 
 
-module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications) {
+module.controller('ClientListCtrl', function($scope, realm, clients, Client, serverInfo, $route, Dialog, Notifications, filterFilter) {
     $scope.realm = realm;
     $scope.clients = clients;
+    $scope.currentPage = 1;
+    $scope.currentPageInput = 1;
+    $scope.pageSize = 20;
+    $scope.numberOfPages = Math.ceil($scope.clients.length/$scope.pageSize);
+
+    $scope.$watch('search', function (newVal, oldVal) {
+        $scope.filtered = filterFilter($scope.clients, newVal);
+        $scope.totalItems = $scope.filtered.length;
+        $scope.numberOfPages = Math.ceil($scope.totalItems/$scope.pageSize);
+        $scope.currentPage = 1;
+        $scope.currentPageInput = 1;
+  }, true);
 
     $scope.removeClient = function(client) {
         Dialog.confirmDelete(client.clientId, 'client', function() {
@@ -1693,8 +1705,10 @@ module.controller('ClientProtocolMapperListCtrl', function($scope, realm, client
     updateMappers();
 });
 
-module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
+module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo, client, clients, mapper, ClientProtocolMapper, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.clients = clients;
+
     /*
     $scope.client = client;
     $scope.create = false;
@@ -1774,8 +1788,9 @@ module.controller('ClientProtocolMapperCtrl', function($scope, realm, serverInfo
 
 });
 
-module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, ClientProtocolMapper, Notifications, Dialog, $location) {
+module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serverInfo, client, clients, ClientProtocolMapper, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.clients = clients;
 
     if (client.protocol == null) {
         client.protocol = 'openid-connect';
@@ -1818,6 +1833,8 @@ module.controller('ClientProtocolMapperCreateCtrl', function($scope, realm, serv
         }, function(error) {
             if (error.status == 400 && error.data.error_description) {
                 Notifications.error(error.data.error_description);
+            } else if (error.status == 409 && error.data.errorMessage) {
+                Notifications.error(error.data.errorMessage);
             } else {
                 Notifications.error('Unexpected error when updating protocol mapper');
             }
@@ -1987,8 +2004,10 @@ module.controller('ClientTemplateProtocolMapperListCtrl', function($scope, realm
     updateMappers();
 });
 
-module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, serverInfo, template, mapper, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
+module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, serverInfo, template, mapper, clients, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.clients = clients;
+
     if (template.protocol == null) {
         template.protocol = 'openid-connect';
     }
@@ -2054,8 +2073,10 @@ module.controller('ClientTemplateProtocolMapperCtrl', function($scope, realm, se
 
 });
 
-module.controller('ClientTemplateProtocolMapperCreateCtrl', function($scope, realm, serverInfo, template, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
+module.controller('ClientTemplateProtocolMapperCreateCtrl', function($scope, realm, serverInfo, template, clients, ClientTemplateProtocolMapper, Notifications, Dialog, $location) {
     $scope.realm = realm;
+    $scope.clients = clients;
+
     if (template.protocol == null) {
         template.protocol = 'openid-connect';
     }
                diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
index 568ebdf..a7135f6 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js
@@ -458,6 +458,7 @@ module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $htt
             var value;
             if (policyToken.indexOf('(') == -1) {
                 id = policyToken.trim();
+                value = null;
             } else {
                 id = policyToken.substring(0, policyToken.indexOf('('));
                 value = policyToken.substring(policyToken.indexOf('(') + 1, policyToken.indexOf(')')).trim();
@@ -492,7 +493,14 @@ module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $htt
 
     $scope.realm = realm;
     $scope.serverInfo = serverInfo;
-    $scope.changed = false; $scope.policy = parse(realm.passwordPolicy);
+
+    $scope.changed = false;
+    $scope.policy = parse(realm.passwordPolicy);
+    var oldCopy = angular.copy($scope.policy);
+
+    $scope.$watch('policy', function() {
+        $scope.changed = ! angular.equals($scope.policy, oldCopy);
+    }, true);
 
     $scope.addPolicy = function(policy){
         policy.value = policy.defaultValue;
@@ -500,21 +508,18 @@ module.controller('RealmPasswordPolicyCtrl', function($scope, Realm, realm, $htt
             $scope.policy = [];
         }
         $scope.policy.push(policy);
-        $scope.changed = true;
     }
 
     $scope.removePolicy = function(index){
         $scope.policy.splice(index, 1);
-        $scope.changed = true;
     }
 
     $scope.save = function() {
-        $scope.changed = false;
         $scope.realm.passwordPolicy = toString($scope.policy);
         console.debug($scope.realm.passwordPolicy);
 
         Realm.update($scope.realm, function () {
-            $location.url("/realms/" + realm.realm + "/authentication/password-policy");
+            $route.reload();
             Notifications.success("Your changes have been saved to the realm.");
         });
     };
@@ -1291,9 +1296,21 @@ module.controller('RealmRevocationCtrl', function($scope, Realm, RealmPushRevoca
 });
 
 
-module.controller('RoleListCtrl', function($scope, $route, Dialog, Notifications, realm, roles, RoleById) {
+module.controller('RoleListCtrl', function($scope, $route, Dialog, Notifications, realm, roles, RoleById, filterFilter) {
     $scope.realm = realm;
     $scope.roles = roles;
+    $scope.currentPage = 1;
+    $scope.currentPageInput = 1;
+    $scope.pageSize = 20;
+    $scope.numberOfPages = Math.ceil($scope.roles.length/$scope.pageSize);
+
+    $scope.$watch('searchQuery', function (newVal, oldVal) {
+        $scope.filtered = filterFilter($scope.roles, {name: newVal});
+        $scope.totalItems = $scope.filtered.length;
+        $scope.numberOfPages = Math.ceil($scope.totalItems/$scope.pageSize);
+        $scope.currentPage = 1;
+        $scope.currentPageInput = 1;
+    }, true);
 
     $scope.removeRole = function (role) {
         Dialog.confirmDelete(role.name, 'role', function () {
@@ -1874,14 +1891,12 @@ module.controller('CreateFlowCtrl', function($scope, realm,
     };
 });
 
-module.controller('CreateExecutionFlowCtrl', function($scope, realm, topFlow, parentFlow, formProviders,
+module.controller('CreateExecutionFlowCtrl', function($scope, realm, parentFlow, formProviders,
                                                       CreateExecutionFlow,
                                                       Notifications, $location) {
     $scope.realm = realm;
     $scope.formProviders = formProviders;
     
-    var returnToTopFlow = parentFlow.topLevel ? parentFlow.alias : topFlow;
-
     var defaultFlowType = parentFlow.providerId == 'client-flow' ? 'client-flow' : 'basic-flow';
     $scope.flow = {
         alias: "",
@@ -1896,23 +1911,21 @@ module.controller('CreateExecutionFlowCtrl', function($scope, realm, topFlow, pa
     $scope.save = function() {
         $scope.flow.provider = $scope.provider.id;
         CreateExecutionFlow.save({realm: realm.realm, alias: parentFlow.alias}, $scope.flow, function() {
-            $location.url("/realms/" + realm.realm + "/authentication/flows/" + returnToTopFlow);
+            $location.url("/realms/" + realm.realm + "/authentication/flows");
             Notifications.success("Flow Created.");
         })
     }
     $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/authentication/flows/" + returnToTopFlow);
+        $location.url("/realms/" + realm.realm + "/authentication/flows");
     };
 });
 
-module.controller('CreateExecutionCtrl', function($scope, realm, topFlow, parentFlow, formActionProviders, authenticatorProviders, clientAuthenticatorProviders,
+module.controller('CreateExecutionCtrl', function($scope, realm, parentFlow, formActionProviders, authenticatorProviders, clientAuthenticatorProviders,
                                                       CreateExecution,
                                                       Notifications, $location) {
     $scope.realm = realm;
     $scope.parentFlow = parentFlow;
     
-    var returnToTopFlow = parentFlow.topLevel ? parentFlow.alias : topFlow;
-    
     if (parentFlow.providerId == 'form-flow') {
         $scope.providers = formActionProviders;
     } else if (parentFlow.providerId == 'client-flow') {
@@ -1931,23 +1944,32 @@ module.controller('CreateExecutionCtrl', function($scope, realm, topFlow, parent
             provider: $scope.provider.id
         }
         CreateExecution.save({realm: realm.realm, alias: parentFlow.alias}, execution, function() {
-            $location.url("/realms/" + realm.realm + "/authentication/flows/" + returnToTopFlow);
+            $location.url("/realms/" + realm.realm + "/authentication/flows");
             Notifications.success("Execution Created.");
         })
     }
     $scope.cancel = function() {
-        $location.url("/realms/" + realm.realm + "/authentication/flows/" + returnToTopFlow);
+        $location.url("/realms/" + realm.realm + "/authentication/flows");
     };
 });
 
 
 
-module.controller('AuthenticationFlowsCtrl', function($scope, $route, realm, flows, selectedFlow,
+module.controller('AuthenticationFlowsCtrl', function($scope, $route, realm, flows, selectedFlow, LastFlowSelected,
                                                       AuthenticationFlows, AuthenticationFlowsCopy, AuthenticationFlowExecutions,
                                                       AuthenticationExecution, AuthenticationExecutionRaisePriority, AuthenticationExecutionLowerPriority,
                                                       $modal, Notifications, CopyDialog, $location) {
     $scope.realm = realm;
     $scope.flows = flows;
+    
+    if (selectedFlow !== null) {
+        LastFlowSelected.alias = selectedFlow;
+    }
+    
+    if (selectedFlow === null && LastFlowSelected.alias !== null) {
+        selectedFlow = LastFlowSelected.alias;
+    }
+    
     if (flows.length > 0) {
         $scope.flow = flows[0];
         if (selectedFlow) {
                diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js
index 73f298e..66ea756 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/services.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js
@@ -347,6 +347,11 @@ module.service('UserSearchState', function() {
     };
 });
 
+// Service tracks the last flow selected in Authentication-->Flows tab
+module.service('LastFlowSelected', function() {
+    this.alias = null;
+});
+
 module.factory('UserFederationInstances', function($resource) {
     return $resource(authUrl + '/admin/realms/:realm/user-federation/instances/:instance', {
         realm : '@realm',
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
index 7f796e9..51aaa20 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-list.html
@@ -4,52 +4,53 @@
         <kc-tooltip>{{:: 'clients.tooltip' | translate}}</kc-tooltip>
     </h1>
 
-    <table class="table table-striped table-bordered">
+    <table class="datatable table table-striped table-bordered dataTable no-footer">
         <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="6">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.clientId" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
-                            <div class="input-group-addon">
-                                <i class="fa fa-search" type="submit"></i>
+            <tr>
+                <th class="kc-table-actions" colspan="6">
+                    <div class="form-inline">
+                        <div class="form-group">
+                            <div class="input-group">
+                            <input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.clientId" class="form-control search" onkeyup="if(event.keyCode === 13){$(this).next('I').click();}">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit"></i>
+                                </div>
                             </div>
                         </div>
-                    </div>
 
-                    <div class="pull-right" data-ng-show="access.manageClients">
-                        <a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">{{:: 'create' | translate}}</a>
-                        <a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">{{:: 'import' | translate}}</a>
+                        <div class="pull-right" data-ng-show="access.manageClients">
+                            <a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">{{:: 'create' | translate}}</a>
+                            <a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">{{:: 'import' | translate}}</a>
+                        </div>
                     </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-hide="clients.length == 0">
-            <th>{{:: 'client-id' | translate}}</th>
-            <th>{{:: 'enabled' | translate}}</th>
-            <th>{{:: 'base-url' | translate}}</th>
-            <th colspan="3">{{:: 'actions' | translate}}</th>
-        </tr>
+                </th>
+            </tr>
+            <tr data-ng-hide="clients.length == 0">
+                <th>{{:: 'client-id' | translate}}</th>
+                <th>{{:: 'enabled' | translate}}</th>
+                <th>{{:: 'base-url' | translate}}</th>
+                <th colspan="3">{{:: 'actions' | translate}}</th>
+            </tr>
         </thead>
         <tbody>
-        <tr ng-repeat="client in clients | filter:search | orderBy:'clientId'">
-            <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
-            <td translate="{{client.enabled}}"></td>
-            <td ng-class="{'text-muted': !client.baseUrl}">
-                <a href="{{client.rootUrl}}{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.rootUrl}}{{client.baseUrl}}</a>
-                <span data-ng-hide="client.baseUrl">{{:: 'not-defined' | translate}}</span>
-            </td>
-            <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</td>
-            <td class="kc-action-cell" data-ng-click="exportClient(client)">{{:: 'export' | translate}}</td>
-            <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
-        </tr>
-        <tr data-ng-show="(clients | filter:search).length == 0">
-            <td class="text-muted" colspan="3" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>
-            <td class="text-muted" colspan="3" data-ng-hide="search.clientId">{{:: 'no-clients-available' | translate}}</td>
-        </tr>
+            <tr ng-repeat="client in clients| filter:search | orderBy:'clientId' | startFrom:(currentPage - 1) * pageSize | limitTo:pageSize">
+                <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
+                <td translate="{{client.enabled}}"></td>
+                <td ng-class="{'text-muted': !client.baseUrl}">
+                    <a href="{{client.rootUrl}}{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.rootUrl}}{{client.baseUrl}}</a>
+                    <span data-ng-hide="client.baseUrl">{{:: 'not-defined' | translate}}</span>
+                </td>
+                <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</td>
+                <td class="kc-action-cell" data-ng-click="exportClient(client)">{{:: 'export' | translate}}</td>
+                <td class="kc-action-cell" data-ng-show="access.manageClients" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</td>
+            </tr>
+            <tr data-ng-show="(clients | filter:search).length == 0">
+                <td class="text-muted" colspan="4" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>
+                <td class="text-muted" colspan="4" data-ng-hide="search.clientId">{{:: 'no-clients-available' | translate}}</td>
+            </tr>
         </tbody>
     </table>
+    <kc-paging current-page='currentPage' number-of-pages='numberOfPages' current-page-input='currentPageInput'></kc-paging>
 </div>
 
 <kc-menu></kc-menu>
\ No newline at end of file
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/menu.html b/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
index eb44793..bc066b0 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
@@ -5,7 +5,7 @@
       <span class="icon-bar"></span>
       <span class="icon-bar"></span>
   </button>
-  <a class="navbar-brand" href="#"></a>
+  <a class="navbar-brand" href="#/"></a>
 </div>
 
 <div class="collapse navbar-collapse" collapse="navCollapsed">
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html b/themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
index e929cad..f211dba 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/password-policy.html
@@ -30,7 +30,7 @@
             <tr ng-repeat="p in policy">
                 <td>{{p.displayName}}</td>
                 <td>
-                    <input type="text" class="form-control" ng-model="p.value" ng-show="p.configType" data-ng-required="!p.configType && !p.defaultValue">
+                    <input type="text" class="form-control" ng-model="p.value" ng-show="p.configType" data-ng-required="p.configType && !p.defaultValue">
                 </td>
                 <td class="kc-action-cell" ng-click="removePolicy($index)">{{:: 'delete' | translate}}</td>
             </tr>
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
index fe781c2..e630bf9 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/protocol-mapper-detail.html
@@ -60,7 +60,7 @@
                 </div>
                 <kc-tooltip>{{model.mapperType.helpText}}</kc-tooltip>
             </div>
-            <kc-provider-config config="model.mapper.config" properties="model.mapperType.properties" realm="model.realm"></kc-provider-config>
+            <kc-provider-config config="model.mapper.config" properties="model.mapperType.properties" realm="model.realm" clients="clients"></kc-provider-config>
         </fieldset>
 
         <div class="form-group">
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/role-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
index 8b2bd26..5c0d473 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/role-list.html
@@ -6,47 +6,48 @@
         <li><a href="#/realms/{{realm.realm}}/default-roles">{{:: 'default-roles' | translate}}</a></li>
     </ul>
 
-    <table class="table table-striped table-bordered">
+    <table class="datatable table table-striped table-bordered dataTable no-footer">
         <thead>
-        <tr>
-            <th class="kc-table-actions" colspan="5">
-                <div class="form-inline">
-                    <div class="form-group">
-                        <div class="input-group">
-                            <input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="searchQuery" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
-                            <div class="input-group-addon">
-                                <i class="fa fa-search" type="submit"></i>
+            <tr>
+                <th class="kc-table-actions" colspan="5">
+                    <div class="form-inline">
+                        <div class="form-group">
+                            <div class="input-group">
+                                <input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="searchQuery" class="form-control search" onkeyup="if (event.keyCode === 13){$(this).next('I').click(); }">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit"></i>
+                                </div>
                             </div>
                         </div>
-                    </div>
 
-                    <div class="pull-right" data-ng-show="access.manageRealm">
-                        <a id="createRole" class="btn btn-default" href="#/create/role/{{realm.realm}}">{{:: 'add-role' | translate}}</a>
+                        <div class="pull-right" data-ng-show="access.manageRealm">
+                            <a id="createRole" class="btn btn-default" href="#/create/role/{{realm.realm}}">{{:: 'add-role' | translate}}</a>
+                        </div>
                     </div>
-                </div>
-            </th>
-        </tr>
-        <tr data-ng-show="roles && roles.length > 0">
-            <th>{{:: 'role-name' | translate}}</th>
-            <th>{{:: 'composite' | translate}}</th>
-            <th>{{:: 'description' | translate}}</th>
-            <th colspan="2">{{:: 'actions' | translate}}</th>
-        </tr>
+                </th>
+            </tr>
+            <tr data-ng-show="roles && roles.length > 0">
+                <th>{{:: 'role-name' | translate}}</th>
+                <th>{{:: 'composite' | translate}}</th>
+                <th>{{:: 'description' | translate}}</th>
+                <th colspan="2">{{:: 'actions' | translate}}</th>
+            </tr>
         </thead>
         <tbody>
-        <tr ng-repeat="role in roles | orderBy:'name' | filter:{name: searchQuery}">
-            <td><a href="#/realms/{{realm.realm}}/roles/{{role.id}}">{{role.name}}</a></td>
-            <td translate="{{role.composite}}"></td>
-            <td>{{role.description}}</td>
-            <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/roles/{{role.id}}">{{:: 'edit' | translate}}</td>
-            <td class="kc-action-cell" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
-        </tr>
-        <tr data-ng-show="(roles | filter:{name: searchQuery}).length == 0">
-            <td class="text-muted" colspan="3" data-ng-show="searchQuery">{{:: 'no-results' | translate}}</td>
-            <td class="text-muted" colspan="3" data-ng-hide="searchQuery">{{:: 'no-realm-roles-available' | translate}}</td>
-        </tr>
+            <tr ng-repeat="role in roles| filter:{name: searchQuery} | orderBy:'name'| startFrom:(currentPage - 1) * pageSize | limitTo:pageSize">
+                <td><a href="#/realms/{{realm.realm}}/roles/{{role.id}}">{{role.name}}</a></td>
+                <td translate="{{role.composite}}"></td>
+                <td>{{role.description}}</td>
+                <td class="kc-action-cell" kc-open="/realms/{{realm.realm}}/roles/{{role.id}}">{{:: 'edit' | translate}}</td>
+                <td class="kc-action-cell" data-ng-click="removeRole(role)">{{:: 'delete' | translate}}</td>
+            </tr>
+            <tr data-ng-show="(roles | filter:{name: searchQuery}).length == 0">
+                <td class="text-muted" colspan="4" data-ng-show="searchQuery">{{:: 'no-results' | translate}}</td>
+                <td class="text-muted" colspan="4" data-ng-hide="searchQuery">{{:: 'no-realm-roles-available' | translate}}</td>
+            </tr>
         </tbody>
     </table>
+    <kc-paging current-page='currentPage' number-of-pages='numberOfPages' current-page-input='currentPageInput'></kc-paging>
 </div>
 
 <kc-menu></kc-menu>
\ No newline at end of file
                diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
index 63bfa7e..670d708 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-consents.html
@@ -13,6 +13,8 @@
             <th>{{:: 'granted-roles' | translate}}</th>
             <th>{{:: 'granted-protocol-mappers' | translate}}</th>
             <th>{{:: 'additional-grants' | translate}}</th>
+            <th>{{:: 'consent-created-date' | translate}}</th>
+            <th>{{:: 'consent-last-updated-date' | translate}}</th>
             <th>{{:: 'action' | translate}}</th>
         </tr>
         </thead>
@@ -41,6 +43,8 @@
                     <span ng-if="!$first">, </span><a href="#/realms/{{realm.realm}}/users/{{user.id}}/offline-sessions/{{additionalGrant.client}}">{{additionalGrant.key}}</a>
                 </span>
             </td>
+            <td>{{consent.createdDate | date :'short'}}</td>
+            <td>{{consent.lastUpdatedDate | date :'short'}}</td>
             <td class="kc-action-cell" ng-click="revokeConsent(consent.clientId)">{{:: 'revoke' | translate}}</td>
         </tr>
         </tbody>
                diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-component-config.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-component-config.html
index dccb17e..b3b536f 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-component-config.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-component-config.html
@@ -12,13 +12,13 @@
             <input ng-model="config[ option.name ][0]" value="'true'" id="option.name" name="option.name" onoffswitchstring on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
         </div>
         <div class="col-md-6" data-ng-show="option.type == 'List'">
-            <select ng-model="config[ option.name ][0]" ng-options="data for data in option.defaultValue">
+            <select ng-model="config[ option.name ][0]" ng-options="data for data in option.options">
                 <option value="" selected> {{:: 'selectOne' | translate}} </option>
             </select>
         </div>
         <div class="col-md-6" data-ng-show="option.type == 'MultivaluedList'">
             <select ui-select2 data-ng-model="config[ option.name ]" data-placeholder="{{:: 'selectMultiple' | translate}}..." multiple>
-                <option ng-repeat="val in option.defaultValue" value="{{val}}" ng-selected="true">{{val}}</option>
+                <option ng-repeat="val in option.options" value="{{val}}" ng-selected="true">{{val}}</option>
             </select>
         </div>
         <div class="col-md-6" data-ng-show="option.type == 'Role'">
                diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-paging.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-paging.html
new file mode 100644
index 0000000..653e4a5
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-paging.html
@@ -0,0 +1,25 @@
+<div ng-hide="numberOfPages < 2" class="dataTables_footer">
+    <div class="dataTables_paginate paging_bootstrap_input">
+        <ul class="pagination">  
+            <li class="first" ng-class="{disabled: !hasPrevious()}" ng-click="firstPage()">
+                <span class="i fa fa-angle-double-left"></span>
+            </li>  
+            <li class="prev" ng-class="{disabled: !hasPrevious()}" ng-click="previousPage()">
+                <span class="i fa fa-angle-left"></span>
+            </li>
+        </ul>
+        <div class="pagination-input">  
+            <input ng-model="currentPageInput" kc-valid-page class="paginate_input" type="text">
+            <span class="paginate_of">of <b>{{numberOfPages}}</b></span>
+        </div>
+        <ul class="pagination">  
+            <li class="next" ng-class="{disabled: !hasNext()}" ng-click="nextPage()">
+                <span class="i fa fa-angle-right"></span>
+            </li>  
+            <li class="last" ng-class="{disabled: !hasNext()}" ng-click="lastPage()">
+                <span class="i fa fa-angle-double-right">
+                </span>
+            </li>
+        </ul>
+    </div>
+</div>
\ No newline at end of file
                diff --git a/themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html b/themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
index 2b5f00e..0309bb3 100755
--- a/themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
+++ b/themes/src/main/resources/theme/base/admin/resources/templates/kc-provider-config.html
@@ -12,7 +12,7 @@
             <input ng-model="config[ option.name ]" value="'true'" name="option.name" id="option.name" onoffswitchstring on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
         </div>
         <div class="col-md-6" data-ng-show="option.type == 'List'">
-            <select ng-model="config[ option.name ]" ng-options="data for data in option.defaultValue">
+            <select ng-model="config[ option.name ]" ng-options="data for data in option.options">
                 <option value="" selected> {{:: 'selectOne' | translate}} </option>
             </select>
         </div>